mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
840 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
559e4e75eb | ||
|
|
8ae84614d5 | ||
|
|
18a7e8b22c | ||
|
|
01120f6120 | ||
|
|
07be6bb5ae | ||
|
|
39b4905ef1 | ||
|
|
6c49a5aa9d | ||
|
|
aaeff2ea0f | ||
|
|
cd48e78667 | ||
|
|
f2ab4e840e | ||
|
|
9a476f8283 | ||
|
|
8e24ad724c | ||
|
|
c70aba2ca5 | ||
|
|
c6a20961b8 | ||
|
|
4741354883 | ||
|
|
a3051f5d58 | ||
|
|
730207e75b | ||
|
|
27e067889d | ||
|
|
22c9433c1c | ||
|
|
c6b558cb3d | ||
|
|
a6d5598c08 | ||
|
|
13ee2abeef | ||
|
|
ca9c841477 | ||
|
|
0dbae3c46c | ||
|
|
045bcbc7da | ||
|
|
9f98e28b08 | ||
|
|
59dfbae9b4 | ||
|
|
3f0250957b | ||
|
|
73595d93f3 | ||
|
|
19b8755c89 | ||
|
|
14aad730de | ||
|
|
6c7eec5778 | ||
|
|
2c5ce5763a | ||
|
|
b568e1387a | ||
|
|
85bd46e457 | ||
|
|
bd4a77992e | ||
|
|
a8750ce8ad | ||
|
|
4e8887c80b | ||
|
|
c38a0cdec9 | ||
|
|
6f961edcb1 | ||
|
|
bdd9f30404 | ||
|
|
f94d5faaf2 | ||
|
|
c1ffd93f28 | ||
|
|
05bf7af859 | ||
|
|
eae359a3b8 | ||
|
|
2156906341 | ||
|
|
e7bd669362 | ||
|
|
17ac5b5e06 | ||
|
|
671cc753b5 | ||
|
|
fd81b47413 | ||
|
|
710b07a857 | ||
|
|
5b93d2642b | ||
|
|
38d792fd97 | ||
|
|
fed266f5ac | ||
|
|
a547d10ab9 | ||
|
|
4cc6043737 | ||
|
|
0a42313b6f | ||
|
|
0b53f541d1 | ||
|
|
ddd17b18d7 | ||
|
|
915f4cc618 | ||
|
|
d4d9b3e461 | ||
|
|
49f5221170 | ||
|
|
96459090a6 | ||
|
|
ccc8b38b77 | ||
|
|
c6d1c8063b | ||
|
|
0ffb6d6362 | ||
|
|
252aaa500e | ||
|
|
d456908e37 | ||
|
|
cd13bfb429 | ||
|
|
ff87bc5889 | ||
|
|
42cd80c172 | ||
|
|
123cd3a092 | ||
|
|
cbc3c4e6eb | ||
|
|
b50e39e5cb | ||
|
|
bbe5ef451a | ||
|
|
c359c0e747 | ||
|
|
99ecb0b60f | ||
|
|
cfc7e45020 | ||
|
|
0307d064ad | ||
|
|
89cd824c70 | ||
|
|
1066e8a5e9 | ||
|
|
d2c31df106 | ||
|
|
a56ffee8f7 | ||
|
|
7c798126e3 | ||
|
|
a755131488 | ||
|
|
648ff65a76 | ||
|
|
854d1c0a1a | ||
|
|
4f561aa9e9 | ||
|
|
8c1c4df10d | ||
|
|
a9e963e84b | ||
|
|
4a509610fe | ||
|
|
7de5066c87 | ||
|
|
24b1be1dd2 | ||
|
|
ee00213961 | ||
|
|
b51b32c758 | ||
|
|
d16e669538 | ||
|
|
50d258fae9 | ||
|
|
494cceff73 | ||
|
|
9885e61962 | ||
|
|
4b88a290c4 | ||
|
|
ee8335e5f1 | ||
|
|
fcde7fdb80 | ||
|
|
3d42da3e97 | ||
|
|
c81a37b740 | ||
|
|
4fa005ade0 | ||
|
|
bf656e892f | ||
|
|
abf074eaf4 | ||
|
|
47657b51ab | ||
|
|
76f8ffeb90 | ||
|
|
e68ae91b59 | ||
|
|
9222c21b4a | ||
|
|
c837d9c91c | ||
|
|
cdf7bef150 | ||
|
|
eb52da9702 | ||
|
|
8a1f2a151d | ||
|
|
1b4ced3e55 | ||
|
|
29cd068dbd | ||
|
|
6681614f1a | ||
|
|
1030db87d4 | ||
|
|
356ab30e89 | ||
|
|
0f09b8df77 | ||
|
|
23c495b939 | ||
|
|
2ac0420903 | ||
|
|
aae070f826 | ||
|
|
6ad825d1e0 | ||
|
|
7910506b3c | ||
|
|
5393d724c5 | ||
|
|
c8b1e4c4e6 | ||
|
|
d373cb602d | ||
|
|
58f195fc04 | ||
|
|
f6675808fc | ||
|
|
aa64712354 | ||
|
|
f6e2185c9c | ||
|
|
08edc8dfab | ||
|
|
ec0760c03e | ||
|
|
b53dfed032 | ||
|
|
96599f26a5 | ||
|
|
c049a7ac76 | ||
|
|
34dabc77c1 | ||
|
|
b4deb6a4e2 | ||
|
|
dd91c0aac2 | ||
|
|
fd983946f5 | ||
|
|
fb18fdf5b7 | ||
|
|
bc7670aa3b | ||
|
|
fe76a4575c | ||
|
|
6addc7cf5f | ||
|
|
eb8b6f4fb5 | ||
|
|
e2a60b7280 | ||
|
|
fe2d0cb514 | ||
|
|
3362ca25be | ||
|
|
c919c2a6fd | ||
|
|
5a70075169 | ||
|
|
42c576cf99 | ||
|
|
1fd26c919b | ||
|
|
c957b558e0 | ||
|
|
ec047c5972 | ||
|
|
08388d12d1 | ||
|
|
850aeaf05e | ||
|
|
6195f4b40e | ||
|
|
92baf77509 | ||
|
|
ab1cdb4c9d | ||
|
|
4f4ff00ecf | ||
|
|
6fe97b42c3 | ||
|
|
c9ac4960bc | ||
|
|
e4d7d22e78 | ||
|
|
eb83cb70ea | ||
|
|
59210dffa9 | ||
|
|
c76cca874b | ||
|
|
d989ce5b44 | ||
|
|
fbc95f2c86 | ||
|
|
9fb8dacadb | ||
|
|
d332aee542 | ||
|
|
f2c97fc2c3 | ||
|
|
5ab84aaa29 | ||
|
|
9842b11815 | ||
|
|
083fb5a1e6 | ||
|
|
98cdd3446b | ||
|
|
9bcbf43695 | ||
|
|
e3c988aa8b | ||
|
|
06be543d32 | ||
|
|
1fd22dcc1c | ||
|
|
e3afdde981 | ||
|
|
698df49e5e | ||
|
|
ff5c90ec5e | ||
|
|
1e075d23b2 | ||
|
|
2b172903b9 | ||
|
|
4654a3ef6c | ||
|
|
9996061f74 | ||
|
|
247a4c40d1 | ||
|
|
1ffbdd9c08 | ||
|
|
f67c0cbd2e | ||
|
|
ff7cc0867b | ||
|
|
ac1a6d3348 | ||
|
|
582bba6c91 | ||
|
|
aaf156478e | ||
|
|
0539c177ab | ||
|
|
fb1323b72f | ||
|
|
dc557dd0e5 | ||
|
|
2d0cfc9c2c | ||
|
|
625a25cd50 | ||
|
|
b8a29d1cd8 | ||
|
|
0fabdf9a01 | ||
|
|
9c3ae795c8 | ||
|
|
de26226fa1 | ||
|
|
121920c074 | ||
|
|
05e19470b2 | ||
|
|
b6680e4aca | ||
|
|
f9d70af841 | ||
|
|
7587581d1f | ||
|
|
8f19976c10 | ||
|
|
8567d68433 | ||
|
|
6542301566 | ||
|
|
a359f77cf6 | ||
|
|
4c9a81f3d8 | ||
|
|
9234b493a3 | ||
|
|
f84425b67c | ||
|
|
8a0c1874dd | ||
|
|
fa23628ae2 | ||
|
|
8a594e673d | ||
|
|
92b9390c51 | ||
|
|
c5c5b2a7b9 | ||
|
|
32a9d0e48b | ||
|
|
80a961bb25 | ||
|
|
d4e227286e | ||
|
|
ba705c8c24 | ||
|
|
b6ae4b173e | ||
|
|
23a28be346 | ||
|
|
a0e24dd36f | ||
|
|
a2cde5e17b | ||
|
|
ecc46e9294 | ||
|
|
20b1190d47 | ||
|
|
29b736bcf7 | ||
|
|
a48bc76ca6 | ||
|
|
305c01cdfa | ||
|
|
88bbdf4696 | ||
|
|
afc11279a9 | ||
|
|
a3fb2a84d5 | ||
|
|
4db23e6677 | ||
|
|
5dd36a7969 | ||
|
|
35a3d0027e | ||
|
|
02789ebd86 | ||
|
|
dfd1846b93 | ||
|
|
872205abc6 | ||
|
|
c52cebd20a | ||
|
|
f449b54f87 | ||
|
|
ffcb6e2f6f | ||
|
|
5daa1aa115 | ||
|
|
1dc009f752 | ||
|
|
009b4ff5e7 | ||
|
|
f1a947af92 | ||
|
|
97c098b1ff | ||
|
|
e252cb6643 | ||
|
|
75c0236e1e | ||
|
|
9c4a98bc25 | ||
|
|
9cba11cde5 | ||
|
|
fac5512b04 | ||
|
|
ed9bf05971 | ||
|
|
19d0f3bdc5 | ||
|
|
2abe53de43 | ||
|
|
37a25750d7 | ||
|
|
d3e288447f | ||
|
|
4a44d2668c | ||
|
|
752b1420a3 | ||
|
|
71705fc91f | ||
|
|
645efc7520 | ||
|
|
b6ee0e5219 | ||
|
|
7acf32debc | ||
|
|
13397f68a3 | ||
|
|
79250722d6 | ||
|
|
04b8748a8f | ||
|
|
2dab8053ea | ||
|
|
f8bab2e465 | ||
|
|
46221a8500 | ||
|
|
8b0e61af8c | ||
|
|
2b0a78811a | ||
|
|
5798cd7176 | ||
|
|
5c25637381 | ||
|
|
8316228771 | ||
|
|
695250155e | ||
|
|
545e606c11 | ||
|
|
52771fdb17 | ||
|
|
de631a1052 | ||
|
|
605398db67 | ||
|
|
407c989860 | ||
|
|
9b4b112a97 | ||
|
|
865b75bcbb | ||
|
|
795b0813cc | ||
|
|
3e1f2b8b9d | ||
|
|
1f0d6f0ac7 | ||
|
|
4ab4f4a67c | ||
|
|
5dbdd5e5e4 | ||
|
|
f03cddf674 | ||
|
|
726e908a49 | ||
|
|
043cd673b8 | ||
|
|
f84173e5cc | ||
|
|
bef7ae7f6c | ||
|
|
33aed95a6c | ||
|
|
282317c46e | ||
|
|
2d6a42ac06 | ||
|
|
cd98f72f10 | ||
|
|
29a98f317e | ||
|
|
6334082e6f | ||
|
|
bd4a6a10f9 | ||
|
|
ea4d988082 | ||
|
|
bf8693a7e8 | ||
|
|
32a67c48e0 | ||
|
|
e93f81ca7a | ||
|
|
8f107f5345 | ||
|
|
741046079c | ||
|
|
df7646fd34 | ||
|
|
d350408161 | ||
|
|
bde55a6fe2 | ||
|
|
83c1bed868 | ||
|
|
6845f026bc | ||
|
|
f2c796bcc5 | ||
|
|
a930daf575 | ||
|
|
36d8e5f295 | ||
|
|
71100679a3 | ||
|
|
e3b61b5b1f | ||
|
|
42a5e7422c | ||
|
|
24782950e4 | ||
|
|
e5639102cb | ||
|
|
b74d05603d | ||
|
|
23fd57f641 | ||
|
|
53ae93751c | ||
|
|
ec8736107c | ||
|
|
9e21ee1bc4 | ||
|
|
31497c2b86 | ||
|
|
0600832ddb | ||
|
|
4a57bd7fd4 | ||
|
|
fbe0c8b9cc | ||
|
|
2e3501366f | ||
|
|
ef7169dbbf | ||
|
|
de9d08075e | ||
|
|
c58f6f2f70 | ||
|
|
56aa5d9657 | ||
|
|
754057b496 | ||
|
|
513c44f07f | ||
|
|
0090655899 | ||
|
|
7103e9be1e | ||
|
|
b04906c3e9 | ||
|
|
fc5fe8b48c | ||
|
|
e32e91af5c | ||
|
|
aa5b026d4a | ||
|
|
9568f3305b | ||
|
|
f33064a1e2 | ||
|
|
6c9a2e96e1 | ||
|
|
8c98f5d928 | ||
|
|
19f0cfcf06 | ||
|
|
4f42d95d3c | ||
|
|
68823c524f | ||
|
|
05917796a5 | ||
|
|
d64da07b7d | ||
|
|
27074a809c | ||
|
|
33b366180e | ||
|
|
d8e310e7bf | ||
|
|
534ddd80ae | ||
|
|
d34f2ec142 | ||
|
|
7381a02dae | ||
|
|
333c7ef61b | ||
|
|
77d5a04aa4 | ||
|
|
d3effdb176 | ||
|
|
d7e1350b95 | ||
|
|
14ac653e45 | ||
|
|
a5e4274cd2 | ||
|
|
16b1095a7b | ||
|
|
3b5b3ffa91 | ||
|
|
7ebcca36d2 | ||
|
|
501c543d1b | ||
|
|
4dafea65f2 | ||
|
|
e7cdd89577 | ||
|
|
1a508439b3 | ||
|
|
3548d103f4 | ||
|
|
b1d4101490 | ||
|
|
a714582c1c | ||
|
|
0e7da0f1a8 | ||
|
|
4f7c8a77f6 | ||
|
|
1842fe6db8 | ||
|
|
1feb31498d | ||
|
|
f3632c44c8 | ||
|
|
32a6e62212 | ||
|
|
575ec07553 | ||
|
|
18308b6525 | ||
|
|
d52f29dcd7 | ||
|
|
288d8047ae | ||
|
|
26b232292c | ||
|
|
1fff69b0aa | ||
|
|
4d347305b5 | ||
|
|
2fd6f8e4ac | ||
|
|
97f316eca7 | ||
|
|
f7ba355697 | ||
|
|
c334040a96 | ||
|
|
b01359e06f | ||
|
|
905f9431a5 | ||
|
|
424951e1bb | ||
|
|
2167d9e4f5 | ||
|
|
82a38a7124 | ||
|
|
eb6a52c55c | ||
|
|
234b8f6abf | ||
|
|
843566eb49 | ||
|
|
d63733830f | ||
|
|
3ebd496c37 | ||
|
|
f0f2b013fc | ||
|
|
9a75509614 | ||
|
|
c513a29bcf | ||
|
|
5d39c884b5 | ||
|
|
6a0f811812 | ||
|
|
f509fb6950 | ||
|
|
33a475a456 | ||
|
|
d2fb90a700 | ||
|
|
a34467dccd | ||
|
|
c6d0f5e3cd | ||
|
|
34c9590cf1 | ||
|
|
a2c7542e48 | ||
|
|
72a9f18456 | ||
|
|
7f59757eea | ||
|
|
3b89020082 | ||
|
|
a7b07eb53f | ||
|
|
58d13dac34 | ||
|
|
5a8921dd22 | ||
|
|
f964dfaa5e | ||
|
|
17274eb397 | ||
|
|
2f0b00a7a1 | ||
|
|
260380abec | ||
|
|
57fc87061d | ||
|
|
cc9f7e723a | ||
|
|
6a41e05694 | ||
|
|
c8e1dc5328 | ||
|
|
c2ee5a0234 | ||
|
|
3cafd2dc69 | ||
|
|
4b8890c438 | ||
|
|
19882dc160 | ||
|
|
0c21023bb2 | ||
|
|
68e6ede47e | ||
|
|
1ed3001358 | ||
|
|
b8ff171127 | ||
|
|
7d16a915ed | ||
|
|
ecc24ce2e9 | ||
|
|
65748351c7 | ||
|
|
a60489b6fd | ||
|
|
e8dbcc31aa | ||
|
|
5dbaf194c5 | ||
|
|
affdb78a65 | ||
|
|
313ddb7879 | ||
|
|
046b416f61 | ||
|
|
2cb311dd24 | ||
|
|
ba36d4b0c8 | ||
|
|
5de1c60d50 | ||
|
|
a8a170ebe6 | ||
|
|
d7937943b0 | ||
|
|
3f1df0ea92 | ||
|
|
caaa3519ad | ||
|
|
58ab271fc1 | ||
|
|
981fedfdd1 | ||
|
|
ac968f9a6a | ||
|
|
ac15b77f89 | ||
|
|
6e4dc1e8ab | ||
|
|
46d17fcb20 | ||
|
|
f91f39afcd | ||
|
|
f317ba327c | ||
|
|
00f4cd5252 | ||
|
|
0a44e20c34 | ||
|
|
abeb1ca49d | ||
|
|
ee3abe745c | ||
|
|
a024c25019 | ||
|
|
5bf3166832 | ||
|
|
7ef293744a | ||
|
|
07df874603 | ||
|
|
687c587d19 | ||
|
|
671255c684 | ||
|
|
c31f324853 | ||
|
|
5b7122bd30 | ||
|
|
4a04100207 | ||
|
|
93652a3115 | ||
|
|
4ad1355af3 | ||
|
|
2501d87840 | ||
|
|
4eae1b7127 | ||
|
|
a71ea9917a | ||
|
|
500e2c43b1 | ||
|
|
e6a4cee86c | ||
|
|
5a94f6819d | ||
|
|
132e3e507d | ||
|
|
ffa06fbb09 | ||
|
|
028e6cd8a8 | ||
|
|
719063e996 | ||
|
|
5d40f36fa8 | ||
|
|
31ffcfc920 | ||
|
|
c9642b70f6 | ||
|
|
849fa57bf6 | ||
|
|
2c95ef76f1 | ||
|
|
4d9cb885b2 | ||
|
|
e375f98f7a | ||
|
|
1b80f3aea2 | ||
|
|
b0496645f1 | ||
|
|
235cb13647 | ||
|
|
504dd9f513 | ||
|
|
e3fedf1676 | ||
|
|
f113a51783 | ||
|
|
f69d5835b8 | ||
|
|
8e8277c0c9 | ||
|
|
c6c4eaf31c | ||
|
|
6324722b65 | ||
|
|
efd8c9ec69 | ||
|
|
9858aa1aa5 | ||
|
|
256a946f96 | ||
|
|
a507964f33 | ||
|
|
7584a6bb29 | ||
|
|
ce6103be30 | ||
|
|
9da4459ab3 | ||
|
|
3b9b9a84cd | ||
|
|
cce0ae4369 | ||
|
|
efb43ac7f9 | ||
|
|
8132a8a7f8 | ||
|
|
9c753cb692 | ||
|
|
514e6675c4 | ||
|
|
18454fd5d0 | ||
|
|
eeb919325e | ||
|
|
959be142ed | ||
|
|
42be91d48d | ||
|
|
908f916656 | ||
|
|
5441c7ed59 | ||
|
|
bea471a0e3 | ||
|
|
4dafee17e0 | ||
|
|
af10be9036 | ||
|
|
1a4e3ab581 | ||
|
|
d9e9cf8967 | ||
|
|
041b0cb561 | ||
|
|
4ad5dde780 | ||
|
|
0bc043a0bb | ||
|
|
c936b7db29 | ||
|
|
2793c49694 | ||
|
|
c578859122 | ||
|
|
43e6f06a9e | ||
|
|
cf8e9f773e | ||
|
|
ed3bdc61f4 | ||
|
|
e57f7d92c3 | ||
|
|
b95eb5cd74 | ||
|
|
b865bbb0d3 | ||
|
|
ca6e1c9a46 | ||
|
|
ea8a2deae6 | ||
|
|
c67237672c | ||
|
|
2d5faa627f | ||
|
|
1562ba4ca0 | ||
|
|
a5d94ac454 | ||
|
|
943fbd8719 | ||
|
|
eea1d57e7e | ||
|
|
74645aa1b7 | ||
|
|
dfd23d9a25 | ||
|
|
27cf16a09c | ||
|
|
0dee9e3ff1 | ||
|
|
9b47dc0ee3 | ||
|
|
c7b9ee92b7 | ||
|
|
ac32e6ca92 | ||
|
|
0c204c3ebb | ||
|
|
016b871734 | ||
|
|
22413b8e7f | ||
|
|
1b50057764 | ||
|
|
9e15058634 | ||
|
|
2a81a7af9e | ||
|
|
6d3d5ebdc5 | ||
|
|
7d63a9e51c | ||
|
|
56a2b3b5ad | ||
|
|
f46f788d80 | ||
|
|
a044b7cf6e | ||
|
|
8afd29e1a2 | ||
|
|
d89b051e6d | ||
|
|
47cf69d2b3 | ||
|
|
35c3c912e7 | ||
|
|
67c5f0229b | ||
|
|
5dcc79555d | ||
|
|
82f741e1dc | ||
|
|
ab21d22514 | ||
|
|
0a599e7337 | ||
|
|
f77bf1ec6b | ||
|
|
ed4fbb4f5a | ||
|
|
f963291970 | ||
|
|
2c3abe33d5 | ||
|
|
0fd7e1d7c2 | ||
|
|
1e23e7efc4 | ||
|
|
46d5d24fcd | ||
|
|
3276c0db9c | ||
|
|
1bdd53a6c5 | ||
|
|
1f2d9ab4e5 | ||
|
|
0806ca442a | ||
|
|
e3a666bfe4 | ||
|
|
6b2dc7a68c | ||
|
|
18c492d9da | ||
|
|
6065caaf19 | ||
|
|
bb4c456f35 | ||
|
|
078a10dcdb | ||
|
|
a8a0c5c0bf | ||
|
|
1a95bd3088 | ||
|
|
cf157fd2d7 | ||
|
|
35ada362d4 | ||
|
|
444b110411 | ||
|
|
1b82fac70e | ||
|
|
dafca1e264 | ||
|
|
69de95df8b | ||
|
|
ca9f64a08b | ||
|
|
3b3e35beb7 | ||
|
|
c087fc430b | ||
|
|
d1a4733939 | ||
|
|
5845109b75 | ||
|
|
7dd2ebdf49 | ||
|
|
3e78322ea4 | ||
|
|
8d6633fcf9 | ||
|
|
1c1f67c091 | ||
|
|
324b1464e4 | ||
|
|
1e9a248a0c | ||
|
|
4319094b02 | ||
|
|
60abebb3a5 | ||
|
|
62f20a4809 | ||
|
|
924326460c | ||
|
|
bba85dc08f | ||
|
|
68678ac4ec | ||
|
|
7f9f383324 | ||
|
|
1239c94fba | ||
|
|
2ab24bbf28 | ||
|
|
a304959933 | ||
|
|
5f0bc729d7 | ||
|
|
e2421bf3c6 | ||
|
|
9b4b21887f | ||
|
|
cc9eaef477 | ||
|
|
c1eecb3512 | ||
|
|
58a26dbca4 | ||
|
|
d06700276f | ||
|
|
ab5b622d70 | ||
|
|
60e21e2530 | ||
|
|
a694c1bd26 | ||
|
|
84d16802a3 | ||
|
|
02fda478ea | ||
|
|
31dcda05b7 | ||
|
|
5479ab1b8a | ||
|
|
cc9c0f9b12 | ||
|
|
aa5a94df5a | ||
|
|
d9b7f413ff | ||
|
|
6c3cf12df6 | ||
|
|
13e0546f56 | ||
|
|
c01dc20284 | ||
|
|
3faf22256e | ||
|
|
ac4d827a9c | ||
|
|
95201409e3 | ||
|
|
89cd474278 | ||
|
|
fc715d58f0 | ||
|
|
217e1c8fae | ||
|
|
5486eed151 | ||
|
|
d1721360ff | ||
|
|
0a0f99dd1b | ||
|
|
eb5ea6f64e | ||
|
|
1d449e9675 | ||
|
|
c82671fce4 | ||
|
|
4c267c4206 | ||
|
|
158e67cf6d | ||
|
|
1afff1a064 | ||
|
|
904874d959 | ||
|
|
d33168d31f | ||
|
|
2b7c4ae438 | ||
|
|
6483565d47 | ||
|
|
11704f7f0c | ||
|
|
8d3f4fac23 | ||
|
|
93b18412f5 | ||
|
|
d9c5f22d1e | ||
|
|
d12ef2b17c | ||
|
|
e8e0b97f6d | ||
|
|
f50083e47a | ||
|
|
461ee350c2 | ||
|
|
0cf4b76876 | ||
|
|
4e1979427d | ||
|
|
110426ac9f | ||
|
|
4565a62634 | ||
|
|
f75da73fca | ||
|
|
5c83edb7b2 | ||
|
|
bb1162f6cc | ||
|
|
a4d2332f9c | ||
|
|
4963ea9b11 | ||
|
|
11caae46c1 | ||
|
|
bfaad9f9bf | ||
|
|
0792ceb21a | ||
|
|
2886f825aa | ||
|
|
22c9b70ca3 | ||
|
|
6dbbebeafb | ||
|
|
f54eeca1fd | ||
|
|
7d6f74083b | ||
|
|
28e4b10fda | ||
|
|
b8405ef7a6 | ||
|
|
d178bb3904 | ||
|
|
1ea512655a | ||
|
|
90463a4a6c | ||
|
|
f340b5ebd0 | ||
|
|
ab2d18ebf0 | ||
|
|
8d3bb1ad80 | ||
|
|
ed3405b5a9 | ||
|
|
904d6b9c78 | ||
|
|
edcd1d0f9f | ||
|
|
a8ce6a9f0e | ||
|
|
42e4a47bfc | ||
|
|
e423fd10c6 | ||
|
|
f73a9e89f6 | ||
|
|
48de49b85d | ||
|
|
da1ee3a3b9 | ||
|
|
79dbc272b8 | ||
|
|
c83cca1d87 | ||
|
|
44b50bee26 | ||
|
|
87b03fdc28 | ||
|
|
b43e05a8fc | ||
|
|
67d7744f7f | ||
|
|
27fb7dc26e | ||
|
|
04168a0359 | ||
|
|
1131db784f | ||
|
|
517fba3686 | ||
|
|
64e17fce3f | ||
|
|
518728ca36 | ||
|
|
d1a7430f80 | ||
|
|
973c522756 | ||
|
|
5536342f9d | ||
|
|
d9ddab1a33 | ||
|
|
c915aac1fa | ||
|
|
a3c2a4db5f | ||
|
|
aebebf5115 | ||
|
|
9a50218400 | ||
|
|
fd5a652270 | ||
|
|
c647a30aa9 | ||
|
|
40d5c78573 | ||
|
|
fe2a9fc2cd | ||
|
|
83f9add68b | ||
|
|
ffe8d16df4 | ||
|
|
31b5672870 | ||
|
|
777fc444ae | ||
|
|
cd5c961dc4 | ||
|
|
c2ea8c4eab | ||
|
|
d6507a945b | ||
|
|
f1abee5d0b | ||
|
|
e4dccc237c | ||
|
|
92d8c740d4 | ||
|
|
b6eddade00 | ||
|
|
04fdd09d1e | ||
|
|
69574aecc6 | ||
|
|
c72d98d4cd | ||
|
|
4f405adea9 | ||
|
|
5217ec375d | ||
|
|
10b264b9ec | ||
|
|
dc741e95bd | ||
|
|
a1ca0a9a02 | ||
|
|
c076c50b68 | ||
|
|
c688db8f08 | ||
|
|
469053de9b | ||
|
|
185b85f86a | ||
|
|
11096a520e | ||
|
|
07fd035aa2 | ||
|
|
6bedcd768f | ||
|
|
0c949db506 | ||
|
|
4c5253c0f5 | ||
|
|
325133e54c | ||
|
|
4113ac574d | ||
|
|
2d6c687913 | ||
|
|
f9fbecc783 | ||
|
|
c5ceba35b6 | ||
|
|
c7a53703b1 | ||
|
|
2151ffcb6a | ||
|
|
e25cb92041 | ||
|
|
c3ed4faec1 | ||
|
|
01de02677f | ||
|
|
6c44e985b1 | ||
|
|
31026e420d | ||
|
|
f2523bdf9f | ||
|
|
5c4d814b63 | ||
|
|
752f479483 | ||
|
|
3a53144bdb | ||
|
|
b0940094f0 | ||
|
|
92904994ef | ||
|
|
112d02eaf5 | ||
|
|
deb8e5bf18 | ||
|
|
fe3eab5815 | ||
|
|
72034da6ac | ||
|
|
2106c353d9 | ||
|
|
27b681bb4c | ||
|
|
ad3e66f903 | ||
|
|
3f7190e884 | ||
|
|
e2fd09df88 | ||
|
|
ebc3923b35 | ||
|
|
30e7de7555 | ||
|
|
15dfc0496e | ||
|
|
3a55653c3e | ||
|
|
1df2fdff3e | ||
|
|
dd16ff5021 | ||
|
|
2633bc4d59 | ||
|
|
e7a8c2b037 | ||
|
|
e292c0986f | ||
|
|
2320330b6a | ||
|
|
8cd12852ce | ||
|
|
51019dc456 | ||
|
|
5a35afadd7 | ||
|
|
63e516ebfe | ||
|
|
7086060724 | ||
|
|
93e4bd8215 | ||
|
|
85fc04598b | ||
|
|
36d4f2602f | ||
|
|
129be9dfe4 | ||
|
|
ed9b82097d | ||
|
|
2fea312187 | ||
|
|
c6b8df0588 | ||
|
|
40cd0d898f | ||
|
|
d6e57f3867 | ||
|
|
c3a5b13301 | ||
|
|
1c7b1d7ff9 | ||
|
|
a1ac86934e | ||
|
|
b0026ff59f | ||
|
|
a5a8a1a06b | ||
|
|
132431b7c8 | ||
|
|
e045d4a0ff | ||
|
|
a41be51385 | ||
|
|
acb0829d81 | ||
|
|
02e0d2acde | ||
|
|
6b6993cc24 | ||
|
|
3af50632d1 | ||
|
|
cd7cb18274 | ||
|
|
7a99ed3c8e | ||
|
|
7d0eaf9a05 | ||
|
|
0b59b930a3 | ||
|
|
5dc015c0a3 | ||
|
|
edd39dfe08 | ||
|
|
f5320e201e | ||
|
|
37569d1526 | ||
|
|
1efeab4078 | ||
|
|
2bff3579e5 | ||
|
|
2fa85c56c2 | ||
|
|
ded55635c1 | ||
|
|
c9b8874eb6 | ||
|
|
9172a1a6f8 | ||
|
|
b2ac7afbcb | ||
|
|
dcfd663c19 | ||
|
|
225f057a5c | ||
|
|
0017e33023 | ||
|
|
76ced16f9e | ||
|
|
245937eb85 | ||
|
|
3a72328d55 | ||
|
|
06bc0300c0 | ||
|
|
98dcf40967 | ||
|
|
6b61ffbb63 | ||
|
|
dd7eef723a |
2
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
2
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
@@ -2,7 +2,7 @@
|
||||
name: Feature request
|
||||
description: Suggest a new feature or improve an existing one
|
||||
title: "[Feature Request]: "
|
||||
labels: ["Enhancement / Feature Request"]
|
||||
labels: ["Enhancement / Feature Request", "FR: Awaiting Consideration"]
|
||||
# assignees:
|
||||
# - octocat
|
||||
body:
|
||||
|
||||
11
.github/workflows/cron_publish_flatpak.yml
vendored
11
.github/workflows/cron_publish_flatpak.yml
vendored
@@ -10,6 +10,7 @@ jobs:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Check if release is needed"
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 180
|
||||
outputs:
|
||||
PCSX2_RELEASE: ${{ steps.getinfo.outputs.PCSX2_RELEASE }}
|
||||
FLATHUB_RELEASE: ${{ steps.getinfo.outputs.FLATHUB_RELEASE }}
|
||||
@@ -23,12 +24,18 @@ jobs:
|
||||
FLATHUB_RELEASE=$(curl -L -s https://flathub.org/api/v2/appstream/net.pcsx2.PCSX2 | jq -r '.releases | max_by(.version) | .version')
|
||||
echo "Latest PCSX2 release is: '${PCSX2_RELEASE}'"
|
||||
echo "Latest Flathub release is: '${FLATHUB_RELEASE}'"
|
||||
PCSX2_RELEASE=$(echo $PCSX2_RELEASE | sed 's/[^0-9]*//g')
|
||||
FLATHUB_RELEASE=$(echo $FLATHUB_RELEASE | sed 's/[^0-9]*//g')
|
||||
echo "PCSX2_RELEASE=${PCSX2_RELEASE}" >> "$GITHUB_OUTPUT"
|
||||
echo "FLATHUB_RELEASE=${FLATHUB_RELEASE}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build:
|
||||
needs: check
|
||||
if: needs.check.outputs.FLATHUB_RELEASE < needs.check.outputs.PCSX2_RELEASE
|
||||
# outputs are automatically compared as strings. This doesn't work in our favour
|
||||
# Use fromJson() to convert them to proper integers...
|
||||
# see: https://github.com/github/docs/pull/25870
|
||||
# and: https://github.com/orgs/community/discussions/57480
|
||||
#if: fromJson(needs.check.outputs.FLATHUB_RELEASE) < fromJson(needs.check.outputs.PCSX2_RELEASE)
|
||||
name: "Build and publish Flatpak"
|
||||
uses: ./.github/workflows/linux_build_flatpak.yml
|
||||
with:
|
||||
@@ -37,7 +44,7 @@ jobs:
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
publish: true
|
||||
branch: stable
|
||||
fetchTags: true
|
||||
stableBuild: false
|
||||
secrets: inherit
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@ jobs:
|
||||
run: ./.github/workflows/scripts/common/update_base_translation.sh
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
uses: peter-evans/create-pull-request@4320041ed380b20e97d388d56a7fb4f9b8c20e79
|
||||
with:
|
||||
title: "Qt: Update Base Translation"
|
||||
commit-message: "Qt: Update Base Translation"
|
||||
commit-message: "[ci skip] Qt: Update Base Translation."
|
||||
committer: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
|
||||
author: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
|
||||
body: "Daily update of base translation sources."
|
||||
|
||||
@@ -19,11 +19,12 @@ jobs:
|
||||
mv ./game_controller_db.txt ${{github.workspace}}/bin/resources/game_controller_db.txt
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
uses: peter-evans/create-pull-request@4320041ed380b20e97d388d56a7fb4f9b8c20e79
|
||||
with:
|
||||
title: "PAD: Update to latest controller database"
|
||||
commit-message: "PAD: Update to latest controller database."
|
||||
commit-message: "[ci skip] PAD: Update to latest controller database."
|
||||
committer: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
|
||||
author: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
|
||||
body: "Weekly automatic update of SDL Controller DB"
|
||||
reviewers: lightningterror
|
||||
body: "Weekly automatic update of SDL Controller DB."
|
||||
branch: update-controller-db
|
||||
delete-branch: true
|
||||
|
||||
41
.github/workflows/linux_build_flatpak.yml
vendored
41
.github/workflows/linux_build_flatpak.yml
vendored
@@ -23,10 +23,6 @@ on:
|
||||
cmakeflags:
|
||||
required: true
|
||||
type: string
|
||||
branch:
|
||||
required: false
|
||||
type: string
|
||||
default: "stable"
|
||||
publish:
|
||||
required: false
|
||||
type: boolean
|
||||
@@ -94,17 +90,12 @@ jobs:
|
||||
cd bin/resources
|
||||
wget "${{ inputs.patchesUrl }}/patches.zip"
|
||||
|
||||
- name: Generate AppStream XML
|
||||
run: |
|
||||
./.github/workflows/scripts/linux/generate-metainfo.sh .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.metainfo.xml
|
||||
cat .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.metainfo.xml
|
||||
# flatpak-builder-lint appstream .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.metainfo.xml
|
||||
|
||||
- name: Validate manifest
|
||||
run: |
|
||||
flatpak-builder-lint manifest .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.json
|
||||
|
||||
- name: Build Flatpak
|
||||
- name: Build Flatpak (beta)
|
||||
if: ${{ inputs.stableBuild == false || inputs.stableBuild == 'false' }}
|
||||
uses: flathub-infra/flatpak-github-actions/flatpak-builder@23796715b3dfa4c86ddf50cf29c3cc8b3c82dca8
|
||||
with:
|
||||
bundle: ${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak
|
||||
@@ -114,17 +105,33 @@ jobs:
|
||||
build-bundle: true
|
||||
verbose: true
|
||||
mirror-screenshots-url: https://dl.flathub.org/media
|
||||
branch: ${{ inputs.branch }}
|
||||
branch: beta
|
||||
cache: true
|
||||
restore-cache: true
|
||||
cache-key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.compiler }} flatpak ${{ hashFiles('.github/workflows/scripts/linux/flatpak/**/*.json', '.github/workflows/scripts/common/*.patch') }}
|
||||
|
||||
- name: Build Flatpak (stable)
|
||||
if: ${{ inputs.stableBuild == true || inputs.stableBuild == 'true' }}
|
||||
uses: flathub-infra/flatpak-github-actions/flatpak-builder@23796715b3dfa4c86ddf50cf29c3cc8b3c82dca8
|
||||
with:
|
||||
bundle: ${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak
|
||||
upload-artifact: false
|
||||
manifest-path: .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.json
|
||||
arch: x86_64
|
||||
build-bundle: true
|
||||
verbose: true
|
||||
mirror-screenshots-url: https://dl.flathub.org/media
|
||||
branch: stable
|
||||
cache: true
|
||||
restore-cache: true
|
||||
cache-key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.compiler }} flatpak ${{ hashFiles('.github/workflows/scripts/linux/flatpak/**/*.json') }}
|
||||
|
||||
|
||||
#- name: Validate build
|
||||
# run: |
|
||||
# flatpak-builder-lint repo repo
|
||||
|
||||
- name: Push to Flathub beta
|
||||
if: inputs.publish == true && inputs.branch == 'beta'
|
||||
- name: Push to Flathub (beta)
|
||||
if: ${{ inputs.publish == true && (inputs.stableBuild == false || inputs.stableBuild == 'false') }}
|
||||
uses: flathub-infra/flatpak-github-actions/flat-manager@23796715b3dfa4c86ddf50cf29c3cc8b3c82dca8
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
@@ -132,8 +139,8 @@ jobs:
|
||||
token: ${{ secrets.FLATHUB_BETA_TOKEN }}
|
||||
build-log-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
- name: Push to Flathub stable
|
||||
if: inputs.publish == true && inputs.branch == 'stable'
|
||||
- name: Push to Flathub (stable)
|
||||
if: ${{ inputs.publish == true && (inputs.stableBuild == true || inputs.stableBuild == 'true') }}
|
||||
uses: flathub-infra/flatpak-github-actions/flat-manager@23796715b3dfa4c86ddf50cf29c3cc8b3c82dca8
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
|
||||
4
.github/workflows/linux_build_matrix.yml
vendored
4
.github/workflows/linux_build_matrix.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
uses: ./.github/workflows/linux_build_qt.yml
|
||||
with:
|
||||
jobName: "AppImage Build"
|
||||
artifactPrefixName: "PCSX2-linux-Qt-x64-appimage-sse4"
|
||||
artifactPrefixName: "PCSX2-linux-Qt-x64-appimage"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
uses: ./.github/workflows/linux_build_flatpak.yml
|
||||
with:
|
||||
jobName: "Flatpak Build"
|
||||
artifactPrefixName: "PCSX2-linux-Qt-x64-flatpak-sse4"
|
||||
artifactPrefixName: "PCSX2-linux-Qt-x64-flatpak"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
publish: false
|
||||
|
||||
14
.github/workflows/linux_build_qt.yml
vendored
14
.github/workflows/linux_build_qt.yml
vendored
@@ -55,19 +55,13 @@ jobs:
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_COMPRESS: true
|
||||
CCACHE_COMPRESSLEVEL: 9
|
||||
CCACHE_MAXSIZE: 100M
|
||||
CCACHE_MAXSIZE: 500M
|
||||
|
||||
steps:
|
||||
# Work around https://github.com/actions/runner-images/issues/8659
|
||||
- name: Remove GCC 13 from runner image
|
||||
shell: bash
|
||||
run: |
|
||||
sudo rm -f /etc/apt/sources.list.d/ubuntu-toolchain-r-ubuntu-test-jammy.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --allow-downgrades 'libc6=2.35-0ubuntu*' 'libc6-dev=2.35-0ubuntu*' libstdc++6=12.3.0-1ubuntu1~22.04 libgcc-s1=12.3.0-1ubuntu1~22.04
|
||||
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# actions/checkout elides tags, fetch them primarily for releases
|
||||
- name: Fetch Tags
|
||||
@@ -123,7 +117,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/deps
|
||||
key: ${{ inputs.os }} ${{ inputs.platform }} deps ${{ hashFiles('.github/workflows/scripts/linux/build-dependencies-qt.sh') }}
|
||||
key: ${{ inputs.os }} ${{ inputs.platform }} deps ${{ hashFiles('.github/workflows/scripts/linux/build-dependencies-qt.sh', '.github/workflows/scripts/common/*.patch') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
|
||||
46
.github/workflows/macos_build.yml
vendored
46
.github/workflows/macos_build.yml
vendored
@@ -25,20 +25,26 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
sign_and_notarize:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build_macos:
|
||||
name: ${{ inputs.jobName }}
|
||||
runs-on: ${{ inputs.os }}
|
||||
# Set some sort of timeout in the event of run-away builds. We are limited on concurrent jobs so, get rid of them.
|
||||
timeout-minutes: 90
|
||||
timeout-minutes: 120
|
||||
env:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
CCACHE_BASEDIR: ${{ github.workspace }}
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_COMPRESS: true
|
||||
CCACHE_COMPRESSLEVEL: 9
|
||||
CCACHE_MAXSIZE: 100M
|
||||
CCACHE_MAXSIZE: 500M
|
||||
# Only way to use a secret in an if statement
|
||||
SIGN_KEY: ${{ secrets.APPLE_SIGN_P12_B64 }}
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
@@ -85,7 +91,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/deps
|
||||
key: ${{ inputs.os }} deps ${{ hashFiles('.github/workflows/scripts/macos/build-dependencies.sh') }}
|
||||
key: ${{ inputs.os }} deps ${{ hashFiles('.github/workflows/scripts/macos/build-dependencies.sh', '.github/workflows/scripts/common/*.patch') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
@@ -143,6 +149,38 @@ jobs:
|
||||
run: make -j$(getconf _NPROCESSORS_ONLN) unittests
|
||||
|
||||
- name: Prepare Build Artifacts
|
||||
run: |
|
||||
mv build/pcsx2*/PCSX2.app PCSX2.app
|
||||
|
||||
- name: Pull the Signing Keys and Notarization Credentials
|
||||
if: ${{ inputs.sign_and_notarize == true && env.SIGN_KEY }}
|
||||
run: |
|
||||
echo "${{ secrets.APPLE_SIGN_P12_B64 }}" | base64 -d > cert.p12
|
||||
echo "${{ secrets.APPLE_APPSTORECONNECT_CFG }}" | base64 -d > key.json
|
||||
|
||||
- name: Sign the Application
|
||||
if: ${{ inputs.sign_and_notarize == true && env.SIGN_KEY }}
|
||||
uses: indygreg/apple-code-sign-action@44d0985b7f4363198e80b6fea63ac3e9dd3e9957
|
||||
with:
|
||||
input_path: 'PCSX2.app'
|
||||
p12_file: cert.p12
|
||||
p12_password: "${{ secrets.APPLE_SIGN_P12_PASS }}"
|
||||
sign_args: |
|
||||
--for-notarization
|
||||
--code-signature-flags=runtime
|
||||
--entitlements-xml-file=pcsx2/Resources/PCSX2.entitlements
|
||||
notarize: true
|
||||
# max_wait_seconds is only present on my fork located at F0bes/apple-code-sign-action@demo4
|
||||
# If we are timing out we should switch to the newest upstream (if I get it upstreamed)
|
||||
# or use my fork.
|
||||
# max_wait_seconds: '2000'
|
||||
staple: true
|
||||
# Generated using rcodesign
|
||||
# Despite what the docs say, I found that this file is required and I had 0 luck
|
||||
# passing the issuer id, key, etc through arguments.
|
||||
app_store_connect_api_key_json_file: 'key.json'
|
||||
|
||||
- name: Zip Build Artifacts
|
||||
run: |
|
||||
TAG="$(git tag --points-at HEAD)"
|
||||
if [ -z "$TAG" ]; then
|
||||
@@ -150,7 +188,7 @@ jobs:
|
||||
else
|
||||
APPNAME="PCSX2-$TAG"
|
||||
fi
|
||||
mv build/pcsx2*/PCSX2.app "$APPNAME.app"
|
||||
mv PCSX2.app "$APPNAME.app"
|
||||
tar --options xz:compression-level=9 -cvJf "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.xz" "$APPNAME.app"
|
||||
mkdir ci-artifacts
|
||||
cp "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.xz" ci-artifacts/macOS.tar.xz
|
||||
|
||||
1
.github/workflows/macos_build_matrix.yml
vendored
1
.github/workflows/macos_build_matrix.yml
vendored
@@ -16,4 +16,5 @@ jobs:
|
||||
with:
|
||||
jobName: "MacOS Build"
|
||||
artifactPrefixName: "PCSX2-macos-Qt"
|
||||
sign_and_notarize: true # If we find that notarization takes a long time we should disable that on PR builds
|
||||
secrets: inherit
|
||||
|
||||
10
.github/workflows/release_cut_new.yml
vendored
10
.github/workflows/release_cut_new.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
# Docs - https://github.com/mathieudutour/github-tag-action
|
||||
- name: Bump Version and Push Tag
|
||||
id: tag_version
|
||||
uses: mathieudutour/github-tag-action@v6.2
|
||||
uses: mathieudutour/github-tag-action@a22cf08638b34d5badda920f9daf6e72c477b07b
|
||||
with:
|
||||
github_token: ${{ github.token }}
|
||||
tag_prefix: v
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
mv ./release-notes.md ${GITHUB_WORKSPACE}/release-notes.md
|
||||
|
||||
- name: Create a GitHub Release (Manual)
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda
|
||||
if: steps.tag_version.outputs.new_tag && github.event_name == 'workflow_dispatch'
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
tag_name: ${{ steps.tag_version.outputs.new_tag }}
|
||||
|
||||
- name: Create a GitHub Release (Push)
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda
|
||||
if: steps.tag_version.outputs.new_tag && github.event_name != 'workflow_dispatch'
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
@@ -114,7 +114,6 @@ jobs:
|
||||
artifactPrefixName: "PCSX2-linux-Qt-x64-flatpak"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
branch: "stable"
|
||||
publish: false
|
||||
fetchTags: true
|
||||
stableBuild: ${{ github.event_name == 'workflow_dispatch' && inputs.is_prelease == 'false' }}
|
||||
@@ -149,6 +148,7 @@ jobs:
|
||||
artifactPrefixName: "PCSX2-macos-Qt"
|
||||
fetchTags: true
|
||||
stableBuild: ${{ github.event_name == 'workflow_dispatch' && inputs.is_prelease == 'false' }}
|
||||
sign_and_notarize: true
|
||||
secrets: inherit
|
||||
|
||||
# Upload the Artifacts
|
||||
@@ -205,7 +205,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: 22
|
||||
|
||||
- name: Announce Release
|
||||
env:
|
||||
|
||||
13
.github/workflows/scripts/common/kddockwidgets-dodgy-include.patch
vendored
Normal file
13
.github/workflows/scripts/common/kddockwidgets-dodgy-include.patch
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
diff --git a/src/core/indicators/ClassicDropIndicatorOverlay.h b/src/core/indicators/ClassicDropIndicatorOverlay.h
|
||||
index 2dfb9718a..9b01f002e 100644
|
||||
--- a/src/core/indicators/ClassicDropIndicatorOverlay.h
|
||||
+++ b/src/core/indicators/ClassicDropIndicatorOverlay.h
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
-#include "core/DropIndicatorOverlay.h"
|
||||
+#include <kddockwidgets/core/DropIndicatorOverlay.h>
|
||||
|
||||
namespace KDDockWidgets {
|
||||
|
||||
@@ -114,6 +114,15 @@ diff --git a/libshaderc/include/shaderc/shaderc.h b/libshaderc/include/shaderc/s
|
||||
index 3a3e97d..65d5b77 100644
|
||||
--- a/libshaderc/include/shaderc/shaderc.h
|
||||
+++ b/libshaderc/include/shaderc/shaderc.h
|
||||
@@ -15,6 +15,8 @@
|
||||
#ifndef SHADERC_SHADERC_H_
|
||||
#define SHADERC_SHADERC_H_
|
||||
|
||||
+#define SHADERC_PCSX2_CUSTOM 1
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -317,7 +317,7 @@ SHADERC_EXPORT void shaderc_compile_options_set_source_language(
|
||||
|
||||
// Sets the compiler mode to generate debug information in the output.
|
||||
@@ -123,69 +132,6 @@ index 3a3e97d..65d5b77 100644
|
||||
|
||||
// Sets the compiler optimization level to the given level. Only the last one
|
||||
// takes effect if multiple calls of this function exist.
|
||||
@@ -506,6 +506,10 @@ SHADERC_EXPORT void shaderc_compile_options_set_invert_y(
|
||||
SHADERC_EXPORT void shaderc_compile_options_set_nan_clamp(
|
||||
shaderc_compile_options_t options, bool enable);
|
||||
|
||||
+// Returns a string representation of the specified compilation status.
|
||||
+SHADERC_EXPORT const char* shaderc_compilation_status_to_string(
|
||||
+ shaderc_compilation_status status);
|
||||
+
|
||||
// An opaque handle to the results of a call to any shaderc_compile_into_*()
|
||||
// function.
|
||||
typedef struct shaderc_compilation_result* shaderc_compilation_result_t;
|
||||
@@ -529,28 +533,31 @@ typedef struct shaderc_compilation_result* shaderc_compilation_result_t;
|
||||
// present. May be safely called from multiple threads without explicit
|
||||
// synchronization. If there was failure in allocating the compiler object,
|
||||
// null will be returned.
|
||||
-SHADERC_EXPORT shaderc_compilation_result_t shaderc_compile_into_spv(
|
||||
+SHADERC_EXPORT shaderc_compilation_status shaderc_compile_into_spv(
|
||||
const shaderc_compiler_t compiler, const char* source_text,
|
||||
size_t source_text_size, shaderc_shader_kind shader_kind,
|
||||
const char* input_file_name, const char* entry_point_name,
|
||||
- const shaderc_compile_options_t additional_options);
|
||||
+ const shaderc_compile_options_t additional_options,
|
||||
+ shaderc_compilation_result_t* result);
|
||||
|
||||
// Like shaderc_compile_into_spv, but the result contains SPIR-V assembly text
|
||||
// instead of a SPIR-V binary module. The SPIR-V assembly syntax is as defined
|
||||
// by the SPIRV-Tools open source project.
|
||||
-SHADERC_EXPORT shaderc_compilation_result_t shaderc_compile_into_spv_assembly(
|
||||
+SHADERC_EXPORT shaderc_compilation_status shaderc_compile_into_spv_assembly(
|
||||
const shaderc_compiler_t compiler, const char* source_text,
|
||||
size_t source_text_size, shaderc_shader_kind shader_kind,
|
||||
const char* input_file_name, const char* entry_point_name,
|
||||
- const shaderc_compile_options_t additional_options);
|
||||
+ const shaderc_compile_options_t additional_options,
|
||||
+ shaderc_compilation_result_t* result);
|
||||
|
||||
// Like shaderc_compile_into_spv, but the result contains preprocessed source
|
||||
// code instead of a SPIR-V binary module
|
||||
-SHADERC_EXPORT shaderc_compilation_result_t shaderc_compile_into_preprocessed_text(
|
||||
+SHADERC_EXPORT shaderc_compilation_status shaderc_compile_into_preprocessed_text(
|
||||
const shaderc_compiler_t compiler, const char* source_text,
|
||||
size_t source_text_size, shaderc_shader_kind shader_kind,
|
||||
const char* input_file_name, const char* entry_point_name,
|
||||
- const shaderc_compile_options_t additional_options);
|
||||
+ const shaderc_compile_options_t additional_options,
|
||||
+ shaderc_compilation_result_t* result);
|
||||
|
||||
// Takes an assembly string of the format defined in the SPIRV-Tools project
|
||||
// (https://github.com/KhronosGroup/SPIRV-Tools/blob/master/syntax.md),
|
||||
@@ -561,10 +568,11 @@ SHADERC_EXPORT shaderc_compilation_result_t shaderc_compile_into_preprocessed_te
|
||||
// May be safely called from multiple threads without explicit synchronization.
|
||||
// If there was failure in allocating the compiler object, null will be
|
||||
// returned.
|
||||
-SHADERC_EXPORT shaderc_compilation_result_t shaderc_assemble_into_spv(
|
||||
+SHADERC_EXPORT shaderc_compilation_status shaderc_assemble_into_spv(
|
||||
const shaderc_compiler_t compiler, const char* source_assembly,
|
||||
size_t source_assembly_size,
|
||||
- const shaderc_compile_options_t additional_options);
|
||||
+ const shaderc_compile_options_t additional_options,
|
||||
+ shaderc_compilation_result_t* result);
|
||||
|
||||
// The following functions, operating on shaderc_compilation_result_t objects,
|
||||
// offer only the basic thread-safety guarantee.
|
||||
diff --git a/libshaderc/include/shaderc/shaderc.hpp b/libshaderc/include/shaderc/shaderc.hpp
|
||||
index 3817af8..5592b49 100644
|
||||
--- a/libshaderc/include/shaderc/shaderc.hpp
|
||||
@@ -202,119 +148,6 @@ index 3817af8..5592b49 100644
|
||||
}
|
||||
|
||||
// Sets the compiler optimization level to the given level. Only the last one
|
||||
@@ -425,9 +426,10 @@ class Compiler {
|
||||
const char* input_file_name,
|
||||
const char* entry_point_name,
|
||||
const CompileOptions& options) const {
|
||||
- shaderc_compilation_result_t compilation_result = shaderc_compile_into_spv(
|
||||
+ shaderc_compilation_result_t compilation_result = nullptr;
|
||||
+ shaderc_compile_into_spv(
|
||||
compiler_, source_text, source_text_size, shader_kind, input_file_name,
|
||||
- entry_point_name, options.options_);
|
||||
+ entry_point_name, options.options_, &compilation_result);
|
||||
return SpvCompilationResult(compilation_result);
|
||||
}
|
||||
|
||||
@@ -451,9 +453,10 @@ class Compiler {
|
||||
size_t source_text_size,
|
||||
shaderc_shader_kind shader_kind,
|
||||
const char* input_file_name) const {
|
||||
- shaderc_compilation_result_t compilation_result =
|
||||
- shaderc_compile_into_spv(compiler_, source_text, source_text_size,
|
||||
- shader_kind, input_file_name, "main", nullptr);
|
||||
+ shaderc_compilation_result_t compilation_result = nullptr;
|
||||
+ shaderc_compile_into_spv(compiler_, source_text, source_text_size,
|
||||
+ shader_kind, input_file_name, "main", nullptr,
|
||||
+ &compilation_result);
|
||||
return SpvCompilationResult(compilation_result);
|
||||
}
|
||||
|
||||
@@ -504,8 +507,11 @@ class Compiler {
|
||||
SpvCompilationResult AssembleToSpv(const char* source_assembly,
|
||||
size_t source_assembly_size,
|
||||
const CompileOptions& options) const {
|
||||
- return SpvCompilationResult(shaderc_assemble_into_spv(
|
||||
- compiler_, source_assembly, source_assembly_size, options.options_));
|
||||
+ shaderc_compilation_result_t compilation_result = nullptr;
|
||||
+ shaderc_assemble_into_spv(
|
||||
+ compiler_, source_assembly, source_assembly_size, options.options_,
|
||||
+ &compilation_result);
|
||||
+ return SpvCompilationResult(compilation_result);
|
||||
}
|
||||
|
||||
// Assembles the given SPIR-V assembly and returns a SPIR-V binary module
|
||||
@@ -513,8 +519,11 @@ class Compiler {
|
||||
// Like the first AssembleToSpv method but uses the default compiler options.
|
||||
SpvCompilationResult AssembleToSpv(const char* source_assembly,
|
||||
size_t source_assembly_size) const {
|
||||
- return SpvCompilationResult(shaderc_assemble_into_spv(
|
||||
- compiler_, source_assembly, source_assembly_size, nullptr));
|
||||
+ shaderc_compilation_result_t compilation_result = nullptr;
|
||||
+ shaderc_assemble_into_spv(
|
||||
+ compiler_, source_assembly, source_assembly_size, nullptr,
|
||||
+ &compilation_result);
|
||||
+ return SpvCompilationResult(compilation_result);
|
||||
}
|
||||
|
||||
// Assembles the given SPIR-V assembly and returns a SPIR-V binary module
|
||||
@@ -523,9 +532,11 @@ class Compiler {
|
||||
// std::string.
|
||||
SpvCompilationResult AssembleToSpv(const std::string& source_assembly,
|
||||
const CompileOptions& options) const {
|
||||
- return SpvCompilationResult(
|
||||
- shaderc_assemble_into_spv(compiler_, source_assembly.data(),
|
||||
- source_assembly.size(), options.options_));
|
||||
+ shaderc_compilation_result_t compilation_result = nullptr;
|
||||
+ shaderc_assemble_into_spv(
|
||||
+ compiler_, source_assembly.data(), source_assembly.size(),
|
||||
+ options.options_, &compilation_result);
|
||||
+ return SpvCompilationResult(compilation_result);
|
||||
}
|
||||
|
||||
// Assembles the given SPIR-V assembly and returns a SPIR-V binary module
|
||||
@@ -533,8 +544,10 @@ class Compiler {
|
||||
// Like the first AssembleToSpv method but the source is provided as a
|
||||
// std::string and also uses default compiler options.
|
||||
SpvCompilationResult AssembleToSpv(const std::string& source_assembly) const {
|
||||
- return SpvCompilationResult(shaderc_assemble_into_spv(
|
||||
- compiler_, source_assembly.data(), source_assembly.size(), nullptr));
|
||||
+ shaderc_compilation_result_t compilation_result = nullptr;
|
||||
+ shaderc_assemble_into_spv(compiler_, source_assembly.data(),
|
||||
+ source_assembly.size(), nullptr, &compilation_result);
|
||||
+ return SpvCompilationResult(compilation_result);
|
||||
}
|
||||
|
||||
// Compiles the given source GLSL and returns the SPIR-V assembly text
|
||||
@@ -544,10 +557,11 @@ class Compiler {
|
||||
const char* source_text, size_t source_text_size,
|
||||
shaderc_shader_kind shader_kind, const char* input_file_name,
|
||||
const char* entry_point_name, const CompileOptions& options) const {
|
||||
- shaderc_compilation_result_t compilation_result =
|
||||
- shaderc_compile_into_spv_assembly(
|
||||
- compiler_, source_text, source_text_size, shader_kind,
|
||||
- input_file_name, entry_point_name, options.options_);
|
||||
+ shaderc_compilation_result_t compilation_result = nullptr;
|
||||
+ shaderc_compile_into_spv_assembly(
|
||||
+ compiler_, source_text, source_text_size, shader_kind,
|
||||
+ input_file_name, entry_point_name, options.options_,
|
||||
+ &compilation_result);
|
||||
return AssemblyCompilationResult(compilation_result);
|
||||
}
|
||||
|
||||
@@ -592,10 +606,10 @@ class Compiler {
|
||||
const char* source_text, size_t source_text_size,
|
||||
shaderc_shader_kind shader_kind, const char* input_file_name,
|
||||
const CompileOptions& options) const {
|
||||
- shaderc_compilation_result_t compilation_result =
|
||||
- shaderc_compile_into_preprocessed_text(
|
||||
+ shaderc_compilation_result_t compilation_result;
|
||||
+ shaderc_compile_into_preprocessed_text(
|
||||
compiler_, source_text, source_text_size, shader_kind,
|
||||
- input_file_name, "main", options.options_);
|
||||
+ input_file_name, "main", options.options_, &compilation_result);
|
||||
return PreprocessedSourceCompilationResult(compilation_result);
|
||||
}
|
||||
|
||||
diff --git a/libshaderc/src/shaderc.cc b/libshaderc/src/shaderc.cc
|
||||
index 63f1bbc..c1a9b12 100644
|
||||
--- a/libshaderc/src/shaderc.cc
|
||||
@@ -334,146 +167,6 @@ index 63f1bbc..c1a9b12 100644
|
||||
}
|
||||
|
||||
void shaderc_compile_options_set_optimization_level(
|
||||
@@ -591,8 +595,31 @@ void shaderc_compiler_release(shaderc_compiler_t compiler) {
|
||||
delete compiler;
|
||||
}
|
||||
|
||||
+const char* shaderc_compilation_status_to_string(shaderc_compilation_status status)
|
||||
+{
|
||||
+ static constexpr const std::pair<shaderc_compilation_status, const char*> status_names[] = {
|
||||
+ {shaderc_compilation_status_success, "shaderc_compilation_status_success"},
|
||||
+ {shaderc_compilation_status_invalid_stage, "shaderc_compilation_status_invalid_stage"},
|
||||
+ {shaderc_compilation_status_compilation_error, "shaderc_compilation_status_compilation_error"},
|
||||
+ {shaderc_compilation_status_internal_error, "shaderc_compilation_status_internal_error"},
|
||||
+ {shaderc_compilation_status_null_result_object, "shaderc_compilation_status_null_result_object"},
|
||||
+ {shaderc_compilation_status_invalid_assembly, "shaderc_compilation_status_invalid_assembly"},
|
||||
+ {shaderc_compilation_status_validation_error, "shaderc_compilation_status_validation_error"},
|
||||
+ {shaderc_compilation_status_transformation_error, "shaderc_compilation_status_transformation_error"},
|
||||
+ {shaderc_compilation_status_configuration_error, "shaderc_compilation_status_configuration_error"},
|
||||
+ };
|
||||
+
|
||||
+ for (const auto& it : status_names)
|
||||
+ {
|
||||
+ if (status == it.first)
|
||||
+ return it.second;
|
||||
+ }
|
||||
+
|
||||
+ return "shaderc_compilation_status_unknown";
|
||||
+}
|
||||
+
|
||||
namespace {
|
||||
-shaderc_compilation_result_t CompileToSpecifiedOutputType(
|
||||
+shaderc_compilation_result_vector* CompileToSpecifiedOutputType(
|
||||
const shaderc_compiler_t compiler, const char* source_text,
|
||||
size_t source_text_size, shaderc_shader_kind shader_kind,
|
||||
const char* input_file_name, const char* entry_point_name,
|
||||
@@ -669,48 +696,59 @@ shaderc_compilation_result_t CompileToSpecifiedOutputType(
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
-shaderc_compilation_result_t shaderc_compile_into_spv(
|
||||
+shaderc_compilation_status shaderc_compile_into_spv(
|
||||
const shaderc_compiler_t compiler, const char* source_text,
|
||||
size_t source_text_size, shaderc_shader_kind shader_kind,
|
||||
const char* input_file_name, const char* entry_point_name,
|
||||
- const shaderc_compile_options_t additional_options) {
|
||||
- return CompileToSpecifiedOutputType(
|
||||
+ const shaderc_compile_options_t additional_options,
|
||||
+ shaderc_compilation_result_t* result) {
|
||||
+ shaderc_compilation_result_vector* resultv = CompileToSpecifiedOutputType(
|
||||
compiler, source_text, source_text_size, shader_kind, input_file_name,
|
||||
entry_point_name, additional_options,
|
||||
shaderc_util::Compiler::OutputType::SpirvBinary);
|
||||
+ *result = resultv;
|
||||
+ return resultv ? resultv->compilation_status : shaderc_compilation_status_internal_error;
|
||||
}
|
||||
|
||||
-shaderc_compilation_result_t shaderc_compile_into_spv_assembly(
|
||||
+shaderc_compilation_status shaderc_compile_into_spv_assembly(
|
||||
const shaderc_compiler_t compiler, const char* source_text,
|
||||
size_t source_text_size, shaderc_shader_kind shader_kind,
|
||||
const char* input_file_name, const char* entry_point_name,
|
||||
- const shaderc_compile_options_t additional_options) {
|
||||
- return CompileToSpecifiedOutputType(
|
||||
+ const shaderc_compile_options_t additional_options,
|
||||
+ shaderc_compilation_result_t* result) {
|
||||
+ shaderc_compilation_result_vector* resultv = CompileToSpecifiedOutputType(
|
||||
compiler, source_text, source_text_size, shader_kind, input_file_name,
|
||||
entry_point_name, additional_options,
|
||||
shaderc_util::Compiler::OutputType::SpirvAssemblyText);
|
||||
+ *result = resultv;
|
||||
+ return resultv ? resultv->compilation_status : shaderc_compilation_status_internal_error;
|
||||
}
|
||||
|
||||
-shaderc_compilation_result_t shaderc_compile_into_preprocessed_text(
|
||||
+shaderc_compilation_status shaderc_compile_into_preprocessed_text(
|
||||
const shaderc_compiler_t compiler, const char* source_text,
|
||||
size_t source_text_size, shaderc_shader_kind shader_kind,
|
||||
const char* input_file_name, const char* entry_point_name,
|
||||
- const shaderc_compile_options_t additional_options) {
|
||||
- return CompileToSpecifiedOutputType(
|
||||
+ const shaderc_compile_options_t additional_options,
|
||||
+ shaderc_compilation_result_t* result) {
|
||||
+ shaderc_compilation_result_vector* resultv = CompileToSpecifiedOutputType(
|
||||
compiler, source_text, source_text_size, shader_kind, input_file_name,
|
||||
entry_point_name, additional_options,
|
||||
shaderc_util::Compiler::OutputType::PreprocessedText);
|
||||
+ *result = resultv;
|
||||
+ return resultv ? resultv->compilation_status : shaderc_compilation_status_internal_error;
|
||||
}
|
||||
|
||||
-shaderc_compilation_result_t shaderc_assemble_into_spv(
|
||||
+shaderc_compilation_status shaderc_assemble_into_spv(
|
||||
const shaderc_compiler_t compiler, const char* source_assembly,
|
||||
size_t source_assembly_size,
|
||||
- const shaderc_compile_options_t additional_options) {
|
||||
- auto* result = new (std::nothrow) shaderc_compilation_result_spv_binary;
|
||||
- if (!result) return nullptr;
|
||||
- result->compilation_status = shaderc_compilation_status_invalid_assembly;
|
||||
- if (!compiler->initializer) return result;
|
||||
- if (source_assembly == nullptr) return result;
|
||||
+ const shaderc_compile_options_t additional_options,
|
||||
+ shaderc_compilation_result_t* result) {
|
||||
+ auto* bresult = new (std::nothrow) shaderc_compilation_result_spv_binary;
|
||||
+ if (!bresult) return shaderc_compilation_status_internal_error;
|
||||
+ bresult->compilation_status = shaderc_compilation_status_invalid_assembly;
|
||||
+ *result = bresult;
|
||||
+ if (!compiler->initializer) return bresult->compilation_status;
|
||||
+ if (source_assembly == nullptr) return bresult->compilation_status;
|
||||
|
||||
TRY_IF_EXCEPTIONS_ENABLED {
|
||||
spv_binary assembling_output_data = nullptr;
|
||||
@@ -724,22 +762,22 @@ shaderc_compilation_result_t shaderc_assemble_into_spv(
|
||||
GetCompilerTargetEnvVersion(target_env_version),
|
||||
{source_assembly, source_assembly + source_assembly_size},
|
||||
&assembling_output_data, &errors);
|
||||
- result->num_errors = !assembling_succeeded;
|
||||
+ bresult->num_errors = !assembling_succeeded;
|
||||
if (assembling_succeeded) {
|
||||
- result->SetOutputData(assembling_output_data);
|
||||
- result->output_data_size =
|
||||
+ bresult->SetOutputData(assembling_output_data);
|
||||
+ bresult->output_data_size =
|
||||
assembling_output_data->wordCount * sizeof(uint32_t);
|
||||
- result->compilation_status = shaderc_compilation_status_success;
|
||||
+ bresult->compilation_status = shaderc_compilation_status_success;
|
||||
} else {
|
||||
- result->messages = std::move(errors);
|
||||
- result->compilation_status = shaderc_compilation_status_invalid_assembly;
|
||||
+ bresult->messages = std::move(errors);
|
||||
+ bresult->compilation_status = shaderc_compilation_status_invalid_assembly;
|
||||
}
|
||||
}
|
||||
CATCH_IF_EXCEPTIONS_ENABLED(...) {
|
||||
- result->compilation_status = shaderc_compilation_status_internal_error;
|
||||
+ bresult->compilation_status = shaderc_compilation_status_internal_error;
|
||||
}
|
||||
|
||||
- return result;
|
||||
+ return bresult->compilation_status;
|
||||
}
|
||||
|
||||
size_t shaderc_result_get_length(const shaderc_compilation_result_t result) {
|
||||
diff --git a/libshaderc_util/include/libshaderc_util/compiler.h b/libshaderc_util/include/libshaderc_util/compiler.h
|
||||
index d9d02b9..b076ec8 100644
|
||||
--- a/libshaderc_util/include/libshaderc_util/compiler.h
|
||||
|
||||
@@ -6,6 +6,9 @@ set -e
|
||||
|
||||
# While we use custom Qt builds for our releases, the Qt6 package will be good enough
|
||||
# for just updating translations. Saves building it for this action alone.
|
||||
"$SCRIPTDIR/../../../../tools/retry.sh" sudo apt-get -y install qt6-l10n-tools
|
||||
"$SCRIPTDIR/../../../../tools/retry.sh" sudo apt-get -y install qt6-l10n-tools python3
|
||||
|
||||
"$SCRIPTDIR/../../../../tools/generate_fullscreen_ui_translation_strings.py"
|
||||
"$SCRIPTDIR/../../../../pcsx2-qt/Translations/update_glyph_ranges.py"
|
||||
"$SCRIPTDIR/../../../../tools/generate_update_fa_glyph_ranges.py"
|
||||
PATH=/usr/lib/qt6/bin:$PATH "$SCRIPTDIR/../../../../pcsx2-qt/Translations/update_base_translation.sh"
|
||||
|
||||
22
.github/workflows/scripts/linux/appimage-qt.sh
vendored
22
.github/workflows/scripts/linux/appimage-qt.sh
vendored
@@ -187,18 +187,16 @@ echo "Generating AppStream metainfo..."
|
||||
mkdir -p "$OUTDIR/usr/share/metainfo"
|
||||
"$SCRIPTDIR/generate-metainfo.sh" "$OUTDIR/usr/share/metainfo/net.pcsx2.PCSX2.appdata.xml"
|
||||
|
||||
# Copy in AppRun hooks.
|
||||
# Unfortunately linuxdeploy is a bit lame and doesn't let us provide our own AppRun hooks, instead
|
||||
# they have to come from plugins.. and screw writing one of those just to disable Wayland.
|
||||
echo "Copying AppRun hooks..."
|
||||
mkdir -p "$OUTDIR/apprun-hooks"
|
||||
for hookpath in "$SCRIPTDIR/apprun-hooks"/*; do
|
||||
hookname=$(basename "$hookpath")
|
||||
cp -v "$hookpath" "$OUTDIR/apprun-hooks/$hookname"
|
||||
sed -i -e 's/exec /source "$this_dir"\/apprun-hooks\/"'"$hookname"'"\nexec /' "$OUTDIR/AppRun"
|
||||
done
|
||||
|
||||
echo "Generating AppImage..."
|
||||
GIT_VERSION=$(git tag --points-at HEAD)
|
||||
|
||||
if [[ "${GIT_VERSION}" == "" ]]; then
|
||||
# In the odd event that we run this script before the release gets tagged.
|
||||
GIT_VERSION=$(git describe --tags || true)
|
||||
if [[ "${GIT_VERSION}" == "" ]]; then
|
||||
GIT_VERSION=$(git rev-parse HEAD)
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f "$NAME.AppImage"
|
||||
$APPIMAGETOOL -v "$OUTDIR" "$NAME.AppImage"
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
if [[ -z "$I_WANT_A_BROKEN_WAYLAND_UI" ]]; then
|
||||
echo "Forcing X11 instead of Wayland, due to various protocol limitations"
|
||||
echo "and Qt issues. If you want to use Wayland, launch PCSX2 with"
|
||||
echo "I_WANT_A_BROKEN_WAYLAND_UI=YES set."
|
||||
export QT_QPA_PLATFORM=xcb
|
||||
else
|
||||
echo "Wayland is not being disabled. Do not complain when things break."
|
||||
fi
|
||||
|
||||
@@ -15,13 +15,14 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
fi
|
||||
|
||||
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEG=9f
|
||||
LIBPNG=1.6.43
|
||||
LIBWEBP=1.4.0
|
||||
LIBJPEGTURBO=3.1.0
|
||||
LIBPNG=1.6.45
|
||||
LIBWEBP=1.5.0
|
||||
LZ4=b8fd2d15309dd4e605070bd4486e26b6ef814e29
|
||||
SDL=SDL2-2.30.5
|
||||
QT=6.7.2
|
||||
ZSTD=1.5.6
|
||||
SDL=SDL3-3.2.10
|
||||
QT=6.9.0
|
||||
ZSTD=1.5.7
|
||||
KDDOCKWIDGETS=2.2.3
|
||||
|
||||
SHADERC=2024.1
|
||||
SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
|
||||
@@ -33,27 +34,28 @@ cd deps-build
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.zip
|
||||
04705c110cb2469caa79fb71fba3d7bf834914706e9641a4589485c1f832565b jpegsrc.v$LIBJPEG.tar.gz
|
||||
6a5ca0652392a2d7c9db2ae5b40210843c0bbc081cbd410825ab00cc59f14a6c libpng-$LIBPNG.tar.xz
|
||||
61f873ec69e3be1b99535634340d5bde750b2e4447caa1db9f61be3fd49ab1e5 libwebp-$LIBWEBP.tar.gz
|
||||
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
926485350139ffb51ef69760db35f78846c805fef3d59bfdcb2fba704663f370 libpng-$LIBPNG.tar.xz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
0728800155f3ed0a0c87e03addbd30ecbe374f7b080678bbca1506051d50dec3 $LZ4.tar.gz
|
||||
f374f3fa29c37dfcc20822d4a7d7dc57e58924d1a5f2ad511bfab4c8193de63b $SDL.tar.gz
|
||||
8c29e06cf42aacc1eafc4077ae2ec6c6fcb96a626157e0593d5e82a34fd403c1 zstd-$ZSTD.tar.gz
|
||||
c5f22a5e10fb162895ded7de0963328e7307611c688487b5d152c9ee64767599 qtbase-everywhere-src-$QT.tar.xz
|
||||
e1a1d8785fae67d16ad0a443b01d5f32663a6b68d275f1806ebab257485ce5d6 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
fb0d1286a35be3583fee34aeb5843c94719e07193bdf1d4d8b0dc14009caef01 qtsvg-everywhere-src-$QT.tar.xz
|
||||
58e855ad1b2533094726c8a425766b63a04a0eede2ed85086860e54593aa4b2a qttools-everywhere-src-$QT.tar.xz
|
||||
9845780b5dc1b7279d57836db51aeaf2e4a1160c42be09750616f39157582ca9 qttranslations-everywhere-src-$QT.tar.xz
|
||||
a2a057e1dd644bd44abb9990fecc194b2e25c2e0f39e81aa9fee4c1e5e2a8a5b qtwayland-everywhere-src-$QT.tar.xz
|
||||
f87be7b4dec66db4098e9c167b2aa34e2ca10aeb5443bdde95ae03185ed513e0 $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
c1800c2ea835801af04a05d4a32321d79a93954ee3ae2172bbeacf13d1f0598c qtbase-everywhere-src-$QT.tar.xz
|
||||
2047c6242a57bf97cf40079fa9f91752c137cd9ae84760faa9a2e5e8a440606f qtimageformats-everywhere-src-$QT.tar.xz
|
||||
ec359d930c95935ea48af58b100c2f5d0d275968ec8ca1e0e76629b7159215fc qtsvg-everywhere-src-$QT.tar.xz
|
||||
fa645589cc3f939022401a926825972a44277dead8ec8607d9f2662e6529c9a4 qttools-everywhere-src-$QT.tar.xz
|
||||
1d5581ef5fc7c7bc556f2403017983683993bbebfcdf977ef8f180f604668c3f qttranslations-everywhere-src-$QT.tar.xz
|
||||
503416fcb04db503bd130e6a49c45e3e546f091e83406f774a0c703130c91805 qtwayland-everywhere-src-$QT.tar.xz
|
||||
eb3b5f0c16313d34f208d90c2fa1e588a23283eed63b101edd5422be6165d528 shaderc-$SHADERC.tar.gz
|
||||
aa27e4454ce631c5a17924ce0624eac736da19fc6f5a2ab15a6c58da7b36950f shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
5d866ce34a4b6908e262e5ebfffc0a5e11dd411640b5f24c85a80ad44c0d4697 shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
03ee1a2c06f3b61008478f4abe9423454e53e580b9488b47c8071547c6a9db47 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
b8529755b2d54205341766ae168e83177c6120660539f9afba71af6bca4b81ec KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
EOF
|
||||
|
||||
curl -C - -L \
|
||||
curl -L \
|
||||
-O "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.zip" \
|
||||
-O "https://ijg.org/files/jpegsrc.v$LIBJPEG.tar.gz" \
|
||||
-O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz" \
|
||||
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz" \
|
||||
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
|
||||
-O "https://github.com/lz4/lz4/archive/$LZ4.tar.gz" \
|
||||
@@ -68,7 +70,8 @@ curl -C - -L \
|
||||
-o "shaderc-$SHADERC.tar.gz" "https://github.com/google/shaderc/archive/refs/tags/v$SHADERC.tar.gz" \
|
||||
-o "shaderc-glslang-$SHADERC_GLSLANG.tar.gz" "https://github.com/KhronosGroup/glslang/archive/$SHADERC_GLSLANG.tar.gz" \
|
||||
-o "shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Headers/archive/$SHADERC_SPIRVHEADERS.tar.gz" \
|
||||
-o "shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Tools/archive/$SHADERC_SPIRVTOOLS.tar.gz"
|
||||
-o "shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Tools/archive/$SHADERC_SPIRVTOOLS.tar.gz" \
|
||||
-o "KDDockWidgets-$KDDOCKWIDGETS.tar.gz" "https://github.com/KDAB/KDDockWidgets/archive/v$KDDOCKWIDGETS.tar.gz"
|
||||
|
||||
shasum -a 256 --check SHASUMS
|
||||
|
||||
@@ -90,16 +93,14 @@ cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building libjpeg..."
|
||||
rm -fr "jpeg-$LIBJPEG"
|
||||
tar xf "jpegsrc.v$LIBJPEG.tar.gz"
|
||||
cd "jpeg-$LIBJPEG"
|
||||
mkdir build
|
||||
cd build
|
||||
../configure --prefix="$INSTALLDIR" --disable-static --enable-shared
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
echo "Building libjpegturbo..."
|
||||
rm -fr "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
tar xf "libjpeg-turbo-$LIBJPEGTURBO.tar.gz"
|
||||
cd "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building LZ4..."
|
||||
rm -fr "lz4-$LZ4"
|
||||
@@ -150,7 +151,7 @@ tar xf "qtbase-everywhere-src-$QT.tar.xz"
|
||||
cd "qtbase-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
../configure -prefix "$INSTALLDIR" -release -dbus-linked -gui -widgets -fontconfig -qt-doubleconversion -ssl -openssl-runtime -opengl desktop -qpa xcb,wayland -xkbcommon -xcb -gtk -- -DFEATURE_dbus=ON -DFEATURE_icu=OFF -DFEATURE_sql=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON
|
||||
../configure -prefix "$INSTALLDIR" -release -dbus-linked -gui -widgets -fontconfig -qt-doubleconversion -ssl -openssl-runtime -opengl desktop -qpa xcb,wayland -xkbcommon -xcb -gtk -- -DFEATURE_dbus=ON -DFEATURE_icu=OFF -DFEATURE_printsupport=OFF -DFEATURE_sql=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON
|
||||
cmake --build . --parallel
|
||||
ninja install
|
||||
cd ../../
|
||||
@@ -192,32 +193,9 @@ echo "Installing Qt Tools..."
|
||||
rm -fr "qttools-everywhere-src-$QT"
|
||||
tar xf "qttools-everywhere-src-$QT.tar.xz"
|
||||
cd "qttools-everywhere-src-$QT"
|
||||
# Force disable clang scanning, it gets very confused.
|
||||
patch -u configure.cmake <<EOF
|
||||
--- configure.cmake
|
||||
+++ configure.cmake
|
||||
@@ -14,12 +14,12 @@
|
||||
# Presumably because 6.0 ClangConfig.cmake files are not good enough?
|
||||
# In any case explicitly request a minimum version of 8.x for now, otherwise
|
||||
# building with CMake will fail at compilation time.
|
||||
-qt_find_package(WrapLibClang 8 PROVIDED_TARGETS WrapLibClang::WrapLibClang)
|
||||
+#qt_find_package(WrapLibClang 8 PROVIDED_TARGETS WrapLibClang::WrapLibClang)
|
||||
# special case end
|
||||
|
||||
-if(TARGET WrapLibClang::WrapLibClang)
|
||||
- set(TEST_libclang "ON" CACHE BOOL "Required libclang version found." FORCE)
|
||||
-endif()
|
||||
+#if(TARGET WrapLibClang::WrapLibClang)
|
||||
+# set(TEST_libclang "ON" CACHE BOOL "Required libclang version found." FORCE)
|
||||
+#endif()
|
||||
|
||||
|
||||
|
||||
EOF
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=ON -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=OFF -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
cmake --build . --parallel
|
||||
ninja install
|
||||
cd ../../
|
||||
@@ -233,6 +211,16 @@ cmake --build . --parallel
|
||||
ninja install
|
||||
cd ../../
|
||||
|
||||
echo "Building KDDockWidgets..."
|
||||
rm -fr "KDDockWidgets-$KDDOCKWIDGETS"
|
||||
tar xf "KDDockWidgets-$KDDOCKWIDGETS.tar.gz"
|
||||
cd "KDDockWidgets-$KDDOCKWIDGETS"
|
||||
patch -p1 < "$SCRIPTDIR/../common/kddockwidgets-dodgy-include.patch"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building shaderc..."
|
||||
rm -fr "shaderc-$SHADERC"
|
||||
tar xf "shaderc-$SHADERC.tar.gz"
|
||||
|
||||
48
.github/workflows/scripts/linux/build-gammaray.sh
vendored
Executable file
48
.github/workflows/scripts/linux/build-gammaray.sh
vendored
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$#" -ne 2 ]; then
|
||||
echo "Syntax: $0 <deps directory> <output directory>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DEPSDIR=$(realpath "$1")
|
||||
INSTALLDIR=$(realpath "$2")
|
||||
|
||||
if [ ! -d "$DEPSDIR/include/QtCore" ]; then
|
||||
echo "Error: The build-dependencies-qt.sh script must be run on the deps directory first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
GAMMARAY=master
|
||||
|
||||
mkdir -p gammaray-build
|
||||
cd gammaray-build
|
||||
|
||||
echo "Downloading..."
|
||||
curl -L -o "GammaRay-$GAMMARAY.tar.gz" https://github.com/KDAB/GammaRay/archive/$GAMMARAY.tar.gz
|
||||
|
||||
rm -fr "GammaRay-$GAMMARAY"
|
||||
|
||||
echo "Extracting..."
|
||||
tar xf "GammaRay-$GAMMARAY.tar.gz"
|
||||
|
||||
cd "GammaRay-$GAMMARAY"
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
echo "Configuring..."
|
||||
cmake -DCMAKE_PREFIX_PATH="$DEPSDIR" -G Ninja -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DGAMMARAY_BUILD_DOCS=false ..
|
||||
|
||||
echo "Building..."
|
||||
cmake --build . --parallel
|
||||
|
||||
echo "Installing..."
|
||||
cmake --build . --target install
|
||||
|
||||
cd ../..
|
||||
|
||||
echo "Cleaning up..."
|
||||
cd ..
|
||||
rm -r gammaray-build
|
||||
@@ -8,8 +8,8 @@
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/the-tcpdump-group/libpcap.git",
|
||||
"tag": "libpcap-1.10.4",
|
||||
"commit": "104271ba4a14de6743e43bcf87536786d8fddea4"
|
||||
"tag": "libpcap-1.10.5",
|
||||
"commit": "bbcbc9174df3298a854daee2b3e666a4b6e5383a"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "sdl2",
|
||||
"name": "sdl3",
|
||||
"buildsystem": "cmake-ninja",
|
||||
"builddir": true,
|
||||
"config-opts": [
|
||||
@@ -14,8 +14,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://libsdl.org/release/SDL2-2.30.5.tar.gz",
|
||||
"sha256": "f374f3fa29c37dfcc20822d4a7d7dc57e58924d1a5f2ad511bfab4c8193de63b"
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.10.tar.gz",
|
||||
"sha256": "f87be7b4dec66db4098e9c167b2aa34e2ca10aeb5443bdde95ae03185ed513e0"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
32
.github/workflows/scripts/linux/flatpak/modules/23-kddockwidgets.json
vendored
Normal file
32
.github/workflows/scripts/linux/flatpak/modules/23-kddockwidgets.json
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "kddockwidgets",
|
||||
"buildsystem": "cmake-ninja",
|
||||
"builddir": true,
|
||||
"config-opts": [
|
||||
"-DKDDockWidgets_QT6=true",
|
||||
"-DKDDockWidgets_EXAMPLES=false",
|
||||
"-DKDDockWidgets_FRONTENDS=qtwidgets"
|
||||
],
|
||||
"build-options": {
|
||||
"strip": true
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/KDAB/KDDockWidgets.git",
|
||||
"tag": "v2.2.3",
|
||||
"commit": "28d16d0431d7cdc9f36cb619d22621146fdfab44",
|
||||
"disable-submodules": true
|
||||
},
|
||||
{
|
||||
"type": "patch",
|
||||
"path": "../../../common/kddockwidgets-dodgy-include.patch"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
"/share/doc/KDDockWidgets-qt6",
|
||||
"/mkspecs/modules/qt_KDDockWidgets.pri",
|
||||
"/lib/cmake",
|
||||
"/include"
|
||||
]
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"app-id": "net.pcsx2.PCSX2",
|
||||
"runtime": "org.kde.Platform",
|
||||
"runtime-version": "6.7",
|
||||
"runtime-version": "6.8",
|
||||
"sdk": "org.kde.Sdk",
|
||||
"sdk-extensions": [
|
||||
"org.freedesktop.Sdk.Extension.llvm17"
|
||||
"org.freedesktop.Sdk.Extension.llvm18"
|
||||
],
|
||||
"add-extensions": {
|
||||
"org.freedesktop.Platform.ffmpeg-full": {
|
||||
"directory": "lib/ffmpeg",
|
||||
"version": "22.08",
|
||||
"version": "24.08",
|
||||
"add-ld-path": ".",
|
||||
"autodownload": true
|
||||
}
|
||||
@@ -19,16 +19,17 @@
|
||||
"--device=all",
|
||||
"--share=network",
|
||||
"--share=ipc",
|
||||
"--socket=x11",
|
||||
"--socket=wayland",
|
||||
"--socket=fallback-x11",
|
||||
"--socket=pulseaudio",
|
||||
"--talk-name=org.freedesktop.ScreenSaver",
|
||||
"--env=QT_QPA_PLATFORM=xcb"
|
||||
"--talk-name=org.freedesktop.ScreenSaver"
|
||||
],
|
||||
"modules": [
|
||||
"modules/10-libpcap.json",
|
||||
"modules/20-sdl2.json",
|
||||
"modules/20-sdl3.json",
|
||||
"modules/21-libbacktrace.json",
|
||||
"modules/22-shaderc.json",
|
||||
"modules/23-kddockwidgets.json",
|
||||
{
|
||||
"name": "pcsx2",
|
||||
"buildsystem": "cmake-ninja",
|
||||
@@ -44,14 +45,14 @@
|
||||
"config-opts": [
|
||||
"-DCMAKE_BUILD_TYPE=Release",
|
||||
"-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON",
|
||||
"-DCMAKE_C_COMPILER=/usr/lib/sdk/llvm17/bin/clang",
|
||||
"-DCMAKE_CXX_COMPILER=/usr/lib/sdk/llvm17/bin/clang++",
|
||||
"-DCMAKE_C_COMPILER=/usr/lib/sdk/llvm18/bin/clang",
|
||||
"-DCMAKE_CXX_COMPILER=/usr/lib/sdk/llvm18/bin/clang++",
|
||||
"-DCMAKE_EXE_LINKER_FLAGS_INIT=-fuse-ld=lld",
|
||||
"-DCMAKE_MODULE_LINKER_FLAGS_INIT=-fuse-ld=lld",
|
||||
"-DCMAKE_SHARED_LINKER_FLAGS_INIT=-fuse-ld=lld",
|
||||
"-DUSE_LINKED_FFMPEG=ON",
|
||||
"-DDISABLE_ADVANCE_SIMD=TRUE"
|
||||
]
|
||||
]
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
@@ -63,8 +64,10 @@
|
||||
"cp -a bin \"${FLATPAK_DEST}\"",
|
||||
"install -Dm644 \"${FLATPAK_BUILDER_BUILDDIR}/bin/resources/icons/AppIconLarge.png\" \"${FLATPAK_DEST}/share/icons/hicolor/512x512/apps/net.pcsx2.PCSX2.png\"",
|
||||
"install -Dm644 \"${FLATPAK_BUILDER_BUILDDIR}/.github/workflows/scripts/linux/pcsx2-qt.desktop\" \"${FLATPAK_DEST}/share/applications/net.pcsx2.PCSX2.desktop\"",
|
||||
"desktop-file-edit --set-key=Icon --set-value=net.pcsx2.PCSX2 \"${FLATPAK_DEST}/share/applications/net.pcsx2.PCSX2.desktop\"",
|
||||
"install -Dm644 \"${FLATPAK_BUILDER_BUILDDIR}/.github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.metainfo.xml\" \"${FLATPAK_DEST}/share/metainfo/net.pcsx2.PCSX2.metainfo.xml\"",
|
||||
"desktop-file-edit --set-key=Icon --set-value=net.pcsx2.PCSX2 \"${FLATPAK_DEST}/share/applications/net.pcsx2.PCSX2.desktop\"",
|
||||
"${FLATPAK_BUILDER_BUILDDIR}/.github/workflows/scripts/linux/generate-metainfo.sh \"${FLATPAK_BUILDER_BUILDDIR}/net.pcsx2.PCSX2.metainfo.xml\"",
|
||||
"cat \"${FLATPAK_BUILDER_BUILDDIR}/net.pcsx2.PCSX2.metainfo.xml\"",
|
||||
"install -Dm644 \"${FLATPAK_BUILDER_BUILDDIR}/net.pcsx2.PCSX2.metainfo.xml\" \"${FLATPAK_DEST}/share/metainfo/net.pcsx2.PCSX2.metainfo.xml\"",
|
||||
"mkdir -p \"${FLATPAK_DEST}/lib/ffmpeg\""
|
||||
]
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 133 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 2.3 MiB |
@@ -1,33 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Uses the AppStream standard https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html -->
|
||||
<component type="desktop">
|
||||
<id>net.pcsx2.PCSX2</id>
|
||||
<launchable type="desktop-id">net.pcsx2.PCSX2.desktop</launchable>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-3.0</project_license>
|
||||
<project_license>GPL-3.0+</project_license>
|
||||
<name>PCSX2</name>
|
||||
<developer_name>PCSX2</developer_name>
|
||||
<summary>PlayStation 2 Emulator</summary>
|
||||
<developer id="net.pcsx2">
|
||||
<name>PCSX2 Team</name>
|
||||
</developer>
|
||||
<summary>PlayStation 2 emulator</summary>
|
||||
<description>
|
||||
<p>PCSX2 is a free and open-source PlayStation 2 (PS2) emulator. Its purpose is to emulate the PS2's hardware, using a combination of MIPS CPU Interpreters, Recompilers and a Virtual Machine which manages hardware states and PS2 system memory. This allows you to play PS2 games on your PC, with many additional features and benefits.</p>
|
||||
<p>PCSX2 is a free and open-source PlayStation 2 (PS2) emulator. Its purpose is to emulate the PS2's hardware, using a combination of MIPS CPU Interpreters, Recompilers, and a Virtual Machine which manages hardware states and PS2 system memory. This allows you to play PS2 games on your PC, with many additional features and benefits.</p>
|
||||
<p>PlayStation 2 and PS2 are registered trademarks of Sony Interactive Entertainment. This application is not affiliated in any way with Sony Interactive Entertainment.</p>
|
||||
</description>
|
||||
<url type="homepage">https://pcsx2.net/</url>
|
||||
<url type="vcs-browser">https://github.com/PCSX2/pcsx2</url>
|
||||
<url type="bugtracker">https://github.com/PCSX2/pcsx2/issues</url>
|
||||
<url type="donation">https://github.com/sponsors/PCSX2</url>
|
||||
<url type="faq">https://pcsx2.net/docs/</url>
|
||||
<url type="help">https://discord.com/invite/TCz3t9k</url>
|
||||
<url type="help">https://pcsx2.net/discord</url>
|
||||
<url type="contribute">https://github.com/PCSX2/pcsx2/blob/master/.github/CONTRIBUTING.md</url>
|
||||
<url type="translate">https://crowdin.com/project/pcsx2-emulator</url>
|
||||
<url type="vcs-browser">https://github.com/PCSX2/pcsx2</url>
|
||||
<url type="contact">https://mastodon.social/@PCSX2</url>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>https://raw.githubusercontent.com/PCSX2/pcsx2/master/.github/workflows/scripts/linux/flatpak/screenshots/screenshot1.png</image>
|
||||
<image>
|
||||
https://raw.githubusercontent.com/PCSX2/pcsx2/master/.github/workflows/scripts/linux/flatpak/screenshots/screenshot1.png
|
||||
</image>
|
||||
<caption>
|
||||
The main PCSX2 Qt interface
|
||||
</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://raw.githubusercontent.com/PCSX2/pcsx2/master/.github/workflows/scripts/linux/flatpak/screenshots/screenshot2.png</image>
|
||||
<image>
|
||||
https://raw.githubusercontent.com/PCSX2/pcsx2/master/.github/workflows/scripts/linux/flatpak/screenshots/screenshot2.png
|
||||
</image>
|
||||
<caption>
|
||||
PCSX2 running a game
|
||||
</caption>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<categories>
|
||||
<category>Game</category>
|
||||
<category>Emulator</category>
|
||||
</categories>
|
||||
<branding>
|
||||
<color type="primary" scheme_preference="light">#3584e4</color>
|
||||
<color type="primary" scheme_preference="dark">#241f31</color>
|
||||
</branding>
|
||||
<supports>
|
||||
<control>keyboard</control>
|
||||
<control>pointing</control>
|
||||
<internet>offline-only</internet>
|
||||
</supports>
|
||||
<recommends>
|
||||
<control>gamepad</control>
|
||||
<memory>8192</memory>
|
||||
</recommends>
|
||||
<requires>
|
||||
<display_length compare="ge">768</display_length>
|
||||
</requires>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<update_contact>stenzek_AT_gmail.com</update_contact>
|
||||
<update_contact>pcsx2_AT_pcsx2.net</update_contact>
|
||||
<releases>
|
||||
<release version="@GIT_VERSION@" date="@GIT_DATE@" />
|
||||
</releases>
|
||||
|
||||
@@ -38,17 +38,18 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
FREETYPE=2.13.2
|
||||
HARFBUZZ=8.3.1
|
||||
SDL=SDL2-2.30.3
|
||||
ZSTD=1.5.5
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=10.0.1
|
||||
SDL=SDL3-3.2.10
|
||||
ZSTD=1.5.7
|
||||
LZ4=b8fd2d15309dd4e605070bd4486e26b6ef814e29
|
||||
LIBPNG=1.6.43
|
||||
LIBJPEG=9f
|
||||
LIBWEBP=1.3.2
|
||||
LIBPNG=1.6.45
|
||||
LIBJPEGTURBO=3.1.0
|
||||
LIBWEBP=1.5.0
|
||||
FFMPEG=6.0
|
||||
MOLTENVK=1.2.8
|
||||
QT=6.7.1
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.7.3
|
||||
KDDOCKWIDGETS=2.2.3
|
||||
|
||||
SHADERC=2024.1
|
||||
SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
|
||||
@@ -74,25 +75,26 @@ CMAKE_ARCH_ARM64=-DCMAKE_OSX_ARCHITECTURES="arm64"
|
||||
CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
12991c4e55c506dd7f9b765933e62fd2be2e06d421505d7950a132e4f1bb484d freetype-$FREETYPE.tar.xz
|
||||
19a54fe9596f7a47c502549fce8e8a10978c697203774008cc173f8360b19a9a harfbuzz-$HARFBUZZ.tar.gz
|
||||
820440072f8f5b50188c1dae104f2ad25984de268785be40c41a099a510f0aec $SDL.tar.gz
|
||||
9c4396cc829cfae319a6e2615202e82aad41372073482fce286fac78646d3ee4 zstd-$ZSTD.tar.gz
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
e7358ea86fe10fb9261931af6f010d4358dac64f7074420ca9bc94aae2bdd542 harfbuzz-$HARFBUZZ.tar.gz
|
||||
f87be7b4dec66db4098e9c167b2aa34e2ca10aeb5443bdde95ae03185ed513e0 $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
0728800155f3ed0a0c87e03addbd30ecbe374f7b080678bbca1506051d50dec3 $LZ4.tar.gz
|
||||
6a5ca0652392a2d7c9db2ae5b40210843c0bbc081cbd410825ab00cc59f14a6c libpng-$LIBPNG.tar.xz
|
||||
2a499607df669e40258e53d0ade8035ba4ec0175244869d1025d460562aa09b4 libwebp-$LIBWEBP.tar.gz
|
||||
04705c110cb2469caa79fb71fba3d7bf834914706e9641a4589485c1f832565b jpegsrc.v$LIBJPEG.tar.gz
|
||||
926485350139ffb51ef69760db35f78846c805fef3d59bfdcb2fba704663f370 libpng-$LIBPNG.tar.xz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
|
||||
85beaf8abfcc54d9da0ff0257ae311abd9e7aa96e53da37e1c37d6bc04ac83cd v$MOLTENVK.tar.gz
|
||||
b7338da1bdccb4d861e714efffaa83f174dfe37e194916bfd7ec82279a6ace19 qtbase-everywhere-src-$QT.tar.xz
|
||||
a733b98f771064d000476b8861f822143982749448ba8abf9f1813edb8dfe79f qtimageformats-everywhere-src-$QT.tar.xz
|
||||
3ed5b80f7228c41dd463b7a57284ed273d224d1c323c0dd78c5209635807cbce qtsvg-everywhere-src-$QT.tar.xz
|
||||
0953cddf6248f3959279a10904892e8a98eb3e463d729a174b6fc47febd99824 qttools-everywhere-src-$QT.tar.xz
|
||||
03d71565872b0e0e7303349071df031ab0f922f6dbdd3a5ec1ade9e188e4fbf4 qttranslations-everywhere-src-$QT.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
8ccbb9ab055205ac76632c9eeddd1ed6fc66936fc56afc2ed0fd5d9e23da3097 qtbase-everywhere-src-$QT.tar.xz
|
||||
9fd58144081654c3373768dd96ead294023830927b14fe3d3c1ef641fb324753 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
40142cb71fb1e07ad612bc361b67f5d54cd9367f9979ae6b86124a064deda06b qtsvg-everywhere-src-$QT.tar.xz
|
||||
f03bb7df619cd9ac9dba110e30b7bcab5dd88eb8bdc9cc752563b4367233203f qttools-everywhere-src-$QT.tar.xz
|
||||
dcc762acac043b9bb5e4d369b6d6f53e0ecfcf76a408fe0db5f7ef071c9d6dc8 qttranslations-everywhere-src-$QT.tar.xz
|
||||
eb3b5f0c16313d34f208d90c2fa1e588a23283eed63b101edd5422be6165d528 shaderc-$SHADERC.tar.gz
|
||||
aa27e4454ce631c5a17924ce0624eac736da19fc6f5a2ab15a6c58da7b36950f shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
5d866ce34a4b6908e262e5ebfffc0a5e11dd411640b5f24c85a80ad44c0d4697 shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
03ee1a2c06f3b61008478f4abe9423454e53e580b9488b47c8071547c6a9db47 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
b8529755b2d54205341766ae168e83177c6120660539f9afba71af6bca4b81ec KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
EOF
|
||||
|
||||
curl -C - -L \
|
||||
@@ -102,7 +104,7 @@ curl -C - -L \
|
||||
-O "https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz" \
|
||||
-O "https://github.com/lz4/lz4/archive/$LZ4.tar.gz" \
|
||||
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz" \
|
||||
-O "https://ijg.org/files/jpegsrc.v$LIBJPEG.tar.gz" \
|
||||
-O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz" \
|
||||
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
|
||||
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
|
||||
-O "https://github.com/KhronosGroup/MoltenVK/archive/refs/tags/v$MOLTENVK.tar.gz" \
|
||||
@@ -114,7 +116,8 @@ curl -C - -L \
|
||||
-o "shaderc-$SHADERC.tar.gz" "https://github.com/google/shaderc/archive/refs/tags/v$SHADERC.tar.gz" \
|
||||
-o "shaderc-glslang-$SHADERC_GLSLANG.tar.gz" "https://github.com/KhronosGroup/glslang/archive/$SHADERC_GLSLANG.tar.gz" \
|
||||
-o "shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Headers/archive/$SHADERC_SPIRVHEADERS.tar.gz" \
|
||||
-o "shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Tools/archive/$SHADERC_SPIRVTOOLS.tar.gz"
|
||||
-o "shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Tools/archive/$SHADERC_SPIRVTOOLS.tar.gz" \
|
||||
-o "KDDockWidgets-$KDDOCKWIDGETS.tar.gz" "https://github.com/KDAB/KDDockWidgets/archive/v$KDDOCKWIDGETS.tar.gz"
|
||||
|
||||
shasum -a 256 --check SHASUMS
|
||||
|
||||
@@ -200,21 +203,12 @@ merge_binaries $(realpath build) $(realpath build-arm64)
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Installing libjpeg..."
|
||||
rm -fr "jpeg-$LIBJPEG"
|
||||
tar xf "jpegsrc.v$LIBJPEG.tar.gz"
|
||||
cd "jpeg-$LIBJPEG"
|
||||
mkdir build
|
||||
cd build
|
||||
../configure --prefix="$INSTALLDIR" --disable-static --enable-shared --host="x86_64-apple-darwin" CFLAGS="-arch x86_64"
|
||||
make "-j$NPROCS"
|
||||
cd ..
|
||||
mkdir build-arm64
|
||||
cd build-arm64
|
||||
../configure --prefix="$INSTALLDIR" --disable-static --enable-shared --host="aarch64-apple-darwin" CFLAGS="-arch arm64"
|
||||
make "-j$NPROCS"
|
||||
cd ..
|
||||
merge_binaries $(realpath build) $(realpath build-arm64)
|
||||
echo "Installing libjpegturbo..."
|
||||
rm -fr "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
tar xf "libjpeg-turbo-$LIBJPEGTURBO.tar.gz"
|
||||
cd "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_ARM64" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build-arm64
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
@@ -330,20 +324,6 @@ echo "Installing Qt Tools..."
|
||||
rm -fr "qttools-everywhere-src-$QT"
|
||||
tar xf "qttools-everywhere-src-$QT.tar.xz"
|
||||
cd "qttools-everywhere-src-$QT"
|
||||
# Linguist relies on a library in the Designer target, which takes 5-7 minutes to build on the CI
|
||||
# Avoid it by not building Linguist, since we only need the tools that come with it
|
||||
patch -u src/linguist/CMakeLists.txt <<EOF
|
||||
--- src/linguist/CMakeLists.txt
|
||||
+++ src/linguist/CMakeLists.txt
|
||||
@@ -14,7 +14,7 @@
|
||||
add_subdirectory(lrelease-pro)
|
||||
add_subdirectory(lupdate)
|
||||
add_subdirectory(lupdate-pro)
|
||||
-if(QT_FEATURE_process AND QT_FEATURE_pushbutton AND QT_FEATURE_toolbutton AND TARGET Qt::Widgets AND NOT no-png)
|
||||
+if(QT_FEATURE_process AND QT_FEATURE_pushbutton AND QT_FEATURE_toolbutton AND TARGET Qt::Widgets AND TARGET Qt::PrintSupport AND NOT no-png)
|
||||
add_subdirectory(linguist)
|
||||
endif()
|
||||
EOF
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=OFF -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
@@ -380,6 +360,16 @@ make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
|
||||
echo "Building KDDockWidgets..."
|
||||
rm -fr "KDDockWidgets-$KDDOCKWIDGETS"
|
||||
tar xf "KDDockWidgets-$KDDOCKWIDGETS.tar.gz"
|
||||
cd "KDDockWidgets-$KDDOCKWIDGETS"
|
||||
patch -p1 < "$SCRIPTDIR/../common/kddockwidgets-dodgy-include.patch"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build
|
||||
cmake --build build --parallel
|
||||
cmake --install build
|
||||
cd ..
|
||||
|
||||
echo "Cleaning up..."
|
||||
cd ..
|
||||
rm -rf deps-build
|
||||
|
||||
@@ -20,17 +20,18 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
FREETYPE=2.13.2
|
||||
HARFBUZZ=8.3.1
|
||||
SDL=SDL2-2.30.5
|
||||
ZSTD=1.5.6
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=10.0.1
|
||||
SDL=SDL3-3.2.10
|
||||
ZSTD=1.5.7
|
||||
LZ4=b8fd2d15309dd4e605070bd4486e26b6ef814e29
|
||||
LIBPNG=1.6.43
|
||||
LIBJPEG=9f
|
||||
LIBWEBP=1.4.0
|
||||
LIBPNG=1.6.45
|
||||
LIBJPEGTURBO=3.1.0
|
||||
LIBWEBP=1.5.0
|
||||
FFMPEG=6.0
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.7.2
|
||||
QT=6.7.3
|
||||
KDDOCKWIDGETS=2.2.3
|
||||
|
||||
SHADERC=2024.1
|
||||
SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
|
||||
@@ -54,25 +55,26 @@ CMAKE_COMMON=(
|
||||
)
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
12991c4e55c506dd7f9b765933e62fd2be2e06d421505d7950a132e4f1bb484d freetype-$FREETYPE.tar.xz
|
||||
19a54fe9596f7a47c502549fce8e8a10978c697203774008cc173f8360b19a9a harfbuzz-$HARFBUZZ.tar.gz
|
||||
f374f3fa29c37dfcc20822d4a7d7dc57e58924d1a5f2ad511bfab4c8193de63b $SDL.tar.gz
|
||||
8c29e06cf42aacc1eafc4077ae2ec6c6fcb96a626157e0593d5e82a34fd403c1 zstd-$ZSTD.tar.gz
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
e7358ea86fe10fb9261931af6f010d4358dac64f7074420ca9bc94aae2bdd542 harfbuzz-$HARFBUZZ.tar.gz
|
||||
f87be7b4dec66db4098e9c167b2aa34e2ca10aeb5443bdde95ae03185ed513e0 $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
0728800155f3ed0a0c87e03addbd30ecbe374f7b080678bbca1506051d50dec3 $LZ4.tar.gz
|
||||
6a5ca0652392a2d7c9db2ae5b40210843c0bbc081cbd410825ab00cc59f14a6c libpng-$LIBPNG.tar.xz
|
||||
61f873ec69e3be1b99535634340d5bde750b2e4447caa1db9f61be3fd49ab1e5 libwebp-$LIBWEBP.tar.gz
|
||||
04705c110cb2469caa79fb71fba3d7bf834914706e9641a4589485c1f832565b jpegsrc.v$LIBJPEG.tar.gz
|
||||
926485350139ffb51ef69760db35f78846c805fef3d59bfdcb2fba704663f370 libpng-$LIBPNG.tar.xz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
c5f22a5e10fb162895ded7de0963328e7307611c688487b5d152c9ee64767599 qtbase-everywhere-src-$QT.tar.xz
|
||||
e1a1d8785fae67d16ad0a443b01d5f32663a6b68d275f1806ebab257485ce5d6 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
fb0d1286a35be3583fee34aeb5843c94719e07193bdf1d4d8b0dc14009caef01 qtsvg-everywhere-src-$QT.tar.xz
|
||||
58e855ad1b2533094726c8a425766b63a04a0eede2ed85086860e54593aa4b2a qttools-everywhere-src-$QT.tar.xz
|
||||
9845780b5dc1b7279d57836db51aeaf2e4a1160c42be09750616f39157582ca9 qttranslations-everywhere-src-$QT.tar.xz
|
||||
8ccbb9ab055205ac76632c9eeddd1ed6fc66936fc56afc2ed0fd5d9e23da3097 qtbase-everywhere-src-$QT.tar.xz
|
||||
9fd58144081654c3373768dd96ead294023830927b14fe3d3c1ef641fb324753 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
40142cb71fb1e07ad612bc361b67f5d54cd9367f9979ae6b86124a064deda06b qtsvg-everywhere-src-$QT.tar.xz
|
||||
f03bb7df619cd9ac9dba110e30b7bcab5dd88eb8bdc9cc752563b4367233203f qttools-everywhere-src-$QT.tar.xz
|
||||
dcc762acac043b9bb5e4d369b6d6f53e0ecfcf76a408fe0db5f7ef071c9d6dc8 qttranslations-everywhere-src-$QT.tar.xz
|
||||
eb3b5f0c16313d34f208d90c2fa1e588a23283eed63b101edd5422be6165d528 shaderc-$SHADERC.tar.gz
|
||||
aa27e4454ce631c5a17924ce0624eac736da19fc6f5a2ab15a6c58da7b36950f shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
5d866ce34a4b6908e262e5ebfffc0a5e11dd411640b5f24c85a80ad44c0d4697 shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
03ee1a2c06f3b61008478f4abe9423454e53e580b9488b47c8071547c6a9db47 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
b8529755b2d54205341766ae168e83177c6120660539f9afba71af6bca4b81ec KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
@@ -82,19 +84,20 @@ curl -L \
|
||||
-O "https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz" \
|
||||
-O "https://github.com/lz4/lz4/archive/$LZ4.tar.gz" \
|
||||
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz" \
|
||||
-O "https://ijg.org/files/jpegsrc.v$LIBJPEG.tar.gz" \
|
||||
-O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz" \
|
||||
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
|
||||
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
|
||||
-O "https://github.com/KhronosGroup/MoltenVK/archive/refs/tags/v$MOLTENVK.tar.gz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
-o "shaderc-$SHADERC.tar.gz" "https://github.com/google/shaderc/archive/refs/tags/v$SHADERC.tar.gz" \
|
||||
-o "shaderc-glslang-$SHADERC_GLSLANG.tar.gz" "https://github.com/KhronosGroup/glslang/archive/$SHADERC_GLSLANG.tar.gz" \
|
||||
-o "shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Headers/archive/$SHADERC_SPIRVHEADERS.tar.gz" \
|
||||
-o "shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Tools/archive/$SHADERC_SPIRVTOOLS.tar.gz"
|
||||
-o "shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Tools/archive/$SHADERC_SPIRVTOOLS.tar.gz" \
|
||||
-o "KDDockWidgets-$KDDOCKWIDGETS.tar.gz" "https://github.com/KDAB/KDDockWidgets/archive/v$KDDOCKWIDGETS.tar.gz"
|
||||
|
||||
shasum -a 256 --check SHASUMS
|
||||
|
||||
@@ -153,16 +156,14 @@ make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Installing libjpeg..."
|
||||
rm -fr "jpeg-$LIBJPEG"
|
||||
tar xf "jpegsrc.v$LIBJPEG.tar.gz"
|
||||
cd "jpeg-$LIBJPEG"
|
||||
mkdir build
|
||||
cd build
|
||||
../configure --prefix="$INSTALLDIR" --disable-static --enable-shared --host="x86_64-apple-darwin" CFLAGS="-arch x86_64"
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
echo "Installing libjpegturbo..."
|
||||
rm -fr "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
tar xf "libjpeg-turbo-$LIBJPEGTURBO.tar.gz"
|
||||
cd "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_X64" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Installing WebP..."
|
||||
rm -fr "libwebp-$LIBWEBP"
|
||||
@@ -180,8 +181,8 @@ rm -fr "freetype-$FREETYPE"
|
||||
tar xf "freetype-$FREETYPE.tar.xz"
|
||||
cd "freetype-$FREETYPE"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DFT_REQUIRE_ZLIB=ON -DFT_REQUIRE_PNG=ON -DFT_DISABLE_BZIP2=TRUE -DFT_DISABLE_BROTLI=TRUE -DFT_DISABLE_HARFBUZZ=TRUE -B build
|
||||
cmake --build build --parallel
|
||||
cmake --install build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building HarfBuzz..."
|
||||
@@ -189,8 +190,8 @@ rm -fr "harfbuzz-$HARFBUZZ"
|
||||
tar xf "harfbuzz-$HARFBUZZ.tar.gz"
|
||||
cd "harfbuzz-$HARFBUZZ"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -B build
|
||||
cmake --build build --parallel
|
||||
cmake --install build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building FreeType with HarfBuzz..."
|
||||
@@ -198,8 +199,8 @@ rm -fr "freetype-$FREETYPE"
|
||||
tar xf "freetype-$FREETYPE.tar.xz"
|
||||
cd "freetype-$FREETYPE"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DFT_REQUIRE_ZLIB=ON -DFT_REQUIRE_PNG=ON -DFT_DISABLE_BZIP2=TRUE -DFT_DISABLE_BROTLI=TRUE -DFT_REQUIRE_HARFBUZZ=TRUE -B build
|
||||
cmake --build build --parallel
|
||||
cmake --install build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
# MoltenVK already builds universal binaries, nothing special to do here.
|
||||
@@ -324,6 +325,16 @@ make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
|
||||
echo "Building KDDockWidgets..."
|
||||
rm -fr "KDDockWidgets-$KDDOCKWIDGETS"
|
||||
tar xf "KDDockWidgets-$KDDOCKWIDGETS.tar.gz"
|
||||
cd "KDDockWidgets-$KDDOCKWIDGETS"
|
||||
patch -p1 < "$SCRIPTDIR/../common/kddockwidgets-dodgy-include.patch"
|
||||
cmake "${CMAKE_COMMON[@]}" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Cleaning up..."
|
||||
cd ..
|
||||
rm -rf deps-build
|
||||
|
||||
640
.github/workflows/scripts/releases/announce-release/package-lock.json
generated
vendored
640
.github/workflows/scripts/releases/announce-release/package-lock.json
generated
vendored
@@ -10,8 +10,8 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@octokit/plugin-retry": "^3.0.9",
|
||||
"@octokit/plugin-throttling": "^3.5.2",
|
||||
"@octokit/rest": "^18.12.0",
|
||||
"@octokit/plugin-throttling": "^9.4.0",
|
||||
"@octokit/rest": "^21.1.1",
|
||||
"discord.js": "^13.2.0"
|
||||
}
|
||||
},
|
||||
@@ -61,45 +61,102 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-token": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
|
||||
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3"
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz",
|
||||
"integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz",
|
||||
"integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==",
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.4.tgz",
|
||||
"integrity": "sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^2.4.4",
|
||||
"@octokit/graphql": "^4.5.8",
|
||||
"@octokit/request": "^5.6.0",
|
||||
"@octokit/request-error": "^2.0.5",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/auth-token": "^5.0.0",
|
||||
"@octokit/graphql": "^8.1.2",
|
||||
"@octokit/request": "^9.2.1",
|
||||
"@octokit/request-error": "^6.1.7",
|
||||
"@octokit/types": "^13.6.2",
|
||||
"before-after-hook": "^3.0.2",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core/node_modules/@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/core/node_modules/@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/endpoint": {
|
||||
"version": "6.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
|
||||
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
|
||||
"version": "10.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz",
|
||||
"integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/types": "^13.6.2",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/endpoint/node_modules/@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
|
||||
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
|
||||
"version": "8.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.1.tgz",
|
||||
"integrity": "sha512-n57hXtOoHrhwTWdvhVkdJHdhTv0JstjDbDRhJfwIRNfFqmSo1DaK/mD2syoNUoLCyqSjBpGAKOG0BuwF392slw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/request": "^5.6.0",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/request": "^9.2.2",
|
||||
"@octokit/types": "^13.8.0",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/graphql/node_modules/@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/openapi-types": {
|
||||
@@ -108,28 +165,75 @@
|
||||
"integrity": "sha512-dWZfYvCCdjZzDYA3lIAMF72Q0jld8xidqCq5Ryw09eBJXZdcM6he0vWBTvw/b5UnGYqexxOyHWgfrsTlUJL3Gw=="
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "2.16.9",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.16.9.tgz",
|
||||
"integrity": "sha512-gfSCMgz5scFKsR0dW4jaYsDJVt/UwCHp4dF7sHlmSekZvwzvLiOAGZ4MQkEsL5DW9hIk2W+UQkYZMTA1b6Wsqw==",
|
||||
"version": "11.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.4.2.tgz",
|
||||
"integrity": "sha512-BXJ7XPCTDXFF+wxcg/zscfgw2O/iDPtNSkwwR1W1W5c4Mb3zav/M2XvxQ23nVmKj7jpweB4g8viMeCQdm7LMVA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.33.0"
|
||||
"@octokit/types": "^13.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-request-log": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
|
||||
"integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz",
|
||||
"integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=3"
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "5.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.12.1.tgz",
|
||||
"integrity": "sha512-0nY3htfl6x9UkPcqv8pm9vOC/bTA7f4IMDWln13neHRdNWQvOQgZ9fRxK7BAc74rye4yVINEFi9Yb9rnGUvosA==",
|
||||
"version": "13.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.3.1.tgz",
|
||||
"integrity": "sha512-o8uOBdsyR+WR8MK9Cco8dCgvG13H1RlM1nWnK/W7TEACQBFux/vPREgKucxUfuDQ5yi1T3hGf4C5ZmZXAERgwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.33.0",
|
||||
"deprecation": "^2.3.1"
|
||||
"@octokit/types": "^13.8.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-retry": {
|
||||
@@ -142,49 +246,107 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-throttling": {
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.7.0.tgz",
|
||||
"integrity": "sha512-qrKT1Yl/KuwGSC6/oHpLBot3ooC9rq0/ryDYBCpkRtoj+R8T47xTMDT6Tk2CxWopFota/8Pi/2SqArqwC0JPow==",
|
||||
"version": "9.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-9.4.0.tgz",
|
||||
"integrity": "sha512-IOlXxXhZA4Z3m0EEYtrrACkuHiArHLZ3CvqWwOez/pURNqRuwfoFlTPbN5Muf28pzFuztxPyiUiNwz8KctdZaQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.1",
|
||||
"@octokit/types": "^13.7.0",
|
||||
"bottleneck": "^2.15.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": "^3.5.0"
|
||||
"@octokit/core": "^6.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-throttling/node_modules/@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-throttling/node_modules/@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "5.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz",
|
||||
"integrity": "sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA==",
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.2.tgz",
|
||||
"integrity": "sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^6.0.1",
|
||||
"@octokit/request-error": "^2.1.0",
|
||||
"@octokit/types": "^6.16.1",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/endpoint": "^10.1.3",
|
||||
"@octokit/request-error": "^6.1.7",
|
||||
"@octokit/types": "^13.6.2",
|
||||
"fast-content-type-parse": "^2.0.0",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request-error": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
|
||||
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
|
||||
"version": "6.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz",
|
||||
"integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
"@octokit/types": "^13.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/request-error/node_modules/@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request/node_modules/@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/request/node_modules/@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest": {
|
||||
"version": "18.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz",
|
||||
"integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==",
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.1.tgz",
|
||||
"integrity": "sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/core": "^3.5.1",
|
||||
"@octokit/plugin-paginate-rest": "^2.16.8",
|
||||
"@octokit/plugin-request-log": "^1.0.4",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^5.12.0"
|
||||
"@octokit/core": "^6.1.4",
|
||||
"@octokit/plugin-paginate-rest": "^11.4.2",
|
||||
"@octokit/plugin-request-log": "^5.3.1",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^13.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/types": {
|
||||
@@ -234,9 +396,10 @@
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"node_modules/before-after-hook": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
|
||||
"integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ=="
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz",
|
||||
"integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/bottleneck": {
|
||||
"version": "2.19.5",
|
||||
@@ -270,11 +433,6 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/deprecation": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||
},
|
||||
"node_modules/discord-api-types": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.23.1.tgz",
|
||||
@@ -316,6 +474,22 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-content-type-parse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz",
|
||||
"integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-obj": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
|
||||
@@ -324,14 +498,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||
@@ -375,14 +541,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/ow": {
|
||||
"version": "0.27.0",
|
||||
"resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz",
|
||||
@@ -429,9 +587,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/universal-user-agent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz",
|
||||
"integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/vali-date": {
|
||||
"version": "1.0.0",
|
||||
@@ -455,11 +614,6 @@
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
||||
@@ -517,45 +671,86 @@
|
||||
}
|
||||
},
|
||||
"@octokit/auth-token": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
|
||||
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.3"
|
||||
}
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz",
|
||||
"integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw=="
|
||||
},
|
||||
"@octokit/core": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz",
|
||||
"integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==",
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.4.tgz",
|
||||
"integrity": "sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==",
|
||||
"requires": {
|
||||
"@octokit/auth-token": "^2.4.4",
|
||||
"@octokit/graphql": "^4.5.8",
|
||||
"@octokit/request": "^5.6.0",
|
||||
"@octokit/request-error": "^2.0.5",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/auth-token": "^5.0.0",
|
||||
"@octokit/graphql": "^8.1.2",
|
||||
"@octokit/request": "^9.2.1",
|
||||
"@octokit/request-error": "^6.1.7",
|
||||
"@octokit/types": "^13.6.2",
|
||||
"before-after-hook": "^3.0.2",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g=="
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"requires": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@octokit/endpoint": {
|
||||
"version": "6.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
|
||||
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
|
||||
"version": "10.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz",
|
||||
"integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/types": "^13.6.2",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g=="
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"requires": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@octokit/graphql": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
|
||||
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
|
||||
"version": "8.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.1.tgz",
|
||||
"integrity": "sha512-n57hXtOoHrhwTWdvhVkdJHdhTv0JstjDbDRhJfwIRNfFqmSo1DaK/mD2syoNUoLCyqSjBpGAKOG0BuwF392slw==",
|
||||
"requires": {
|
||||
"@octokit/request": "^5.6.0",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/request": "^9.2.2",
|
||||
"@octokit/types": "^13.8.0",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g=="
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"requires": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@octokit/openapi-types": {
|
||||
@@ -564,26 +759,55 @@
|
||||
"integrity": "sha512-dWZfYvCCdjZzDYA3lIAMF72Q0jld8xidqCq5Ryw09eBJXZdcM6he0vWBTvw/b5UnGYqexxOyHWgfrsTlUJL3Gw=="
|
||||
},
|
||||
"@octokit/plugin-paginate-rest": {
|
||||
"version": "2.16.9",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.16.9.tgz",
|
||||
"integrity": "sha512-gfSCMgz5scFKsR0dW4jaYsDJVt/UwCHp4dF7sHlmSekZvwzvLiOAGZ4MQkEsL5DW9hIk2W+UQkYZMTA1b6Wsqw==",
|
||||
"version": "11.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.4.2.tgz",
|
||||
"integrity": "sha512-BXJ7XPCTDXFF+wxcg/zscfgw2O/iDPtNSkwwR1W1W5c4Mb3zav/M2XvxQ23nVmKj7jpweB4g8viMeCQdm7LMVA==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.33.0"
|
||||
"@octokit/types": "^13.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g=="
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"requires": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-request-log": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
|
||||
"integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz",
|
||||
"integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==",
|
||||
"requires": {}
|
||||
},
|
||||
"@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "5.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.12.1.tgz",
|
||||
"integrity": "sha512-0nY3htfl6x9UkPcqv8pm9vOC/bTA7f4IMDWln13neHRdNWQvOQgZ9fRxK7BAc74rye4yVINEFi9Yb9rnGUvosA==",
|
||||
"version": "13.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.3.1.tgz",
|
||||
"integrity": "sha512-o8uOBdsyR+WR8MK9Cco8dCgvG13H1RlM1nWnK/W7TEACQBFux/vPREgKucxUfuDQ5yi1T3hGf4C5ZmZXAERgwQ==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.33.0",
|
||||
"deprecation": "^2.3.1"
|
||||
"@octokit/types": "^13.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g=="
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"requires": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-retry": {
|
||||
@@ -596,46 +820,88 @@
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-throttling": {
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.7.0.tgz",
|
||||
"integrity": "sha512-qrKT1Yl/KuwGSC6/oHpLBot3ooC9rq0/ryDYBCpkRtoj+R8T47xTMDT6Tk2CxWopFota/8Pi/2SqArqwC0JPow==",
|
||||
"version": "9.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-9.4.0.tgz",
|
||||
"integrity": "sha512-IOlXxXhZA4Z3m0EEYtrrACkuHiArHLZ3CvqWwOez/pURNqRuwfoFlTPbN5Muf28pzFuztxPyiUiNwz8KctdZaQ==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.1",
|
||||
"@octokit/types": "^13.7.0",
|
||||
"bottleneck": "^2.15.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g=="
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"requires": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@octokit/request": {
|
||||
"version": "5.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz",
|
||||
"integrity": "sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA==",
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.2.tgz",
|
||||
"integrity": "sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==",
|
||||
"requires": {
|
||||
"@octokit/endpoint": "^6.0.1",
|
||||
"@octokit/request-error": "^2.1.0",
|
||||
"@octokit/types": "^6.16.1",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/endpoint": "^10.1.3",
|
||||
"@octokit/request-error": "^6.1.7",
|
||||
"@octokit/types": "^13.6.2",
|
||||
"fast-content-type-parse": "^2.0.0",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g=="
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"requires": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@octokit/request-error": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
|
||||
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
|
||||
"version": "6.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz",
|
||||
"integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
"@octokit/types": "^13.6.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g=="
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"requires": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@octokit/rest": {
|
||||
"version": "18.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz",
|
||||
"integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==",
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.1.tgz",
|
||||
"integrity": "sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==",
|
||||
"requires": {
|
||||
"@octokit/core": "^3.5.1",
|
||||
"@octokit/plugin-paginate-rest": "^2.16.8",
|
||||
"@octokit/plugin-request-log": "^1.0.4",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^5.12.0"
|
||||
"@octokit/core": "^6.1.4",
|
||||
"@octokit/plugin-paginate-rest": "^11.4.2",
|
||||
"@octokit/plugin-request-log": "^5.3.1",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^13.3.0"
|
||||
}
|
||||
},
|
||||
"@octokit/types": {
|
||||
@@ -675,9 +941,9 @@
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"before-after-hook": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
|
||||
"integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ=="
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz",
|
||||
"integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A=="
|
||||
},
|
||||
"bottleneck": {
|
||||
"version": "2.19.5",
|
||||
@@ -702,11 +968,6 @@
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"deprecation": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||
},
|
||||
"discord-api-types": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.23.1.tgz",
|
||||
@@ -735,16 +996,16 @@
|
||||
"is-obj": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"fast-content-type-parse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz",
|
||||
"integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q=="
|
||||
},
|
||||
"is-obj": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
|
||||
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="
|
||||
},
|
||||
"is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
|
||||
},
|
||||
"lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||
@@ -771,14 +1032,6 @@
|
||||
"whatwg-url": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"ow": {
|
||||
"version": "0.27.0",
|
||||
"resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz",
|
||||
@@ -813,9 +1066,9 @@
|
||||
"integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA=="
|
||||
},
|
||||
"universal-user-agent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz",
|
||||
"integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q=="
|
||||
},
|
||||
"vali-date": {
|
||||
"version": "1.0.0",
|
||||
@@ -836,11 +1089,6 @@
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@octokit/plugin-retry": "^3.0.9",
|
||||
"@octokit/plugin-throttling": "^3.5.2",
|
||||
"@octokit/rest": "^18.12.0",
|
||||
"@octokit/plugin-throttling": "^9.4.0",
|
||||
"@octokit/rest": "^21.1.1",
|
||||
"discord.js": "^13.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
440
.github/workflows/scripts/releases/generate-release-notes/package-lock.json
generated
vendored
440
.github/workflows/scripts/releases/generate-release-notes/package-lock.json
generated
vendored
@@ -1,202 +1,332 @@
|
||||
{
|
||||
"name": "generate-release-notes",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
|
||||
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.3"
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@octokit/plugin-retry": "^3.0.9",
|
||||
"@octokit/plugin-throttling": "^9.6.0",
|
||||
"@octokit/rest": "^21.1.1"
|
||||
}
|
||||
},
|
||||
"@octokit/core": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz",
|
||||
"integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==",
|
||||
"requires": {
|
||||
"@octokit/auth-token": "^2.4.4",
|
||||
"@octokit/graphql": "^4.5.8",
|
||||
"@octokit/request": "^5.6.0",
|
||||
"@octokit/request-error": "^2.0.5",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"node_modules/@octokit/auth-token": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz",
|
||||
"integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"@octokit/endpoint": {
|
||||
"version": "6.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
|
||||
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"node_modules/@octokit/core": {
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.4.tgz",
|
||||
"integrity": "sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^5.0.0",
|
||||
"@octokit/graphql": "^8.1.2",
|
||||
"@octokit/request": "^9.2.1",
|
||||
"@octokit/request-error": "^6.1.7",
|
||||
"@octokit/types": "^13.6.2",
|
||||
"before-after-hook": "^3.0.2",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"@octokit/graphql": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
|
||||
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
|
||||
"requires": {
|
||||
"@octokit/request": "^5.6.0",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"node_modules/@octokit/core/node_modules/@octokit/openapi-types": {
|
||||
"version": "24.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/core/node_modules/@octokit/types": {
|
||||
"version": "13.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^24.2.0"
|
||||
}
|
||||
},
|
||||
"@octokit/openapi-types": {
|
||||
"node_modules/@octokit/endpoint": {
|
||||
"version": "10.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz",
|
||||
"integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.6.2",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": {
|
||||
"version": "24.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/endpoint/node_modules/@octokit/types": {
|
||||
"version": "13.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^24.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql": {
|
||||
"version": "8.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.1.tgz",
|
||||
"integrity": "sha512-n57hXtOoHrhwTWdvhVkdJHdhTv0JstjDbDRhJfwIRNfFqmSo1DaK/mD2syoNUoLCyqSjBpGAKOG0BuwF392slw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/request": "^9.2.2",
|
||||
"@octokit/types": "^13.8.0",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": {
|
||||
"version": "24.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/graphql/node_modules/@octokit/types": {
|
||||
"version": "13.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^24.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/openapi-types": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.1.0.tgz",
|
||||
"integrity": "sha512-dWZfYvCCdjZzDYA3lIAMF72Q0jld8xidqCq5Ryw09eBJXZdcM6he0vWBTvw/b5UnGYqexxOyHWgfrsTlUJL3Gw=="
|
||||
},
|
||||
"@octokit/plugin-paginate-rest": {
|
||||
"version": "2.16.9",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.16.9.tgz",
|
||||
"integrity": "sha512-gfSCMgz5scFKsR0dW4jaYsDJVt/UwCHp4dF7sHlmSekZvwzvLiOAGZ4MQkEsL5DW9hIk2W+UQkYZMTA1b6Wsqw==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.33.0"
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-request-log": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
|
||||
"integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA=="
|
||||
},
|
||||
"@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "5.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.12.1.tgz",
|
||||
"integrity": "sha512-0nY3htfl6x9UkPcqv8pm9vOC/bTA7f4IMDWln13neHRdNWQvOQgZ9fRxK7BAc74rye4yVINEFi9Yb9rnGUvosA==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.33.0",
|
||||
"deprecation": "^2.3.1"
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-retry": {
|
||||
"node_modules/@octokit/plugin-retry": {
|
||||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-3.0.9.tgz",
|
||||
"integrity": "sha512-r+fArdP5+TG6l1Rv/C9hVoty6tldw6cE2pRHNGmFPdyfrc696R6JjrQ3d7HdVqGwuzfyrcaLAKD7K8TX8aehUQ==",
|
||||
"requires": {
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"bottleneck": "^2.15.3"
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-throttling": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.5.2.tgz",
|
||||
"integrity": "sha512-Eu7kfJxU8vmHqWGNszWpg+GVp2tnAfax3XQV5CkYPEE69C+KvInJXW9WajgSeW+cxYe0UVdouzCtcreGNuJo7A==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.1",
|
||||
"node_modules/@octokit/plugin-throttling": {
|
||||
"version": "9.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-9.6.0.tgz",
|
||||
"integrity": "sha512-zn7m1N3vpJDaVzLqjCRdJ0cRzNiekHEWPi8Ww9xyPNrDt5PStHvVE0eR8wy4RSU8Eg7YO8MHyvn6sv25EGVhhg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.7.0",
|
||||
"bottleneck": "^2.15.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": "^6.1.3"
|
||||
}
|
||||
},
|
||||
"@octokit/request": {
|
||||
"version": "5.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz",
|
||||
"integrity": "sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA==",
|
||||
"requires": {
|
||||
"@octokit/endpoint": "^6.0.1",
|
||||
"@octokit/request-error": "^2.1.0",
|
||||
"@octokit/types": "^6.16.1",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"node_modules/@octokit/plugin-throttling/node_modules/@octokit/openapi-types": {
|
||||
"version": "24.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-throttling/node_modules/@octokit/types": {
|
||||
"version": "13.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^24.2.0"
|
||||
}
|
||||
},
|
||||
"@octokit/request-error": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
|
||||
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.2.tgz",
|
||||
"integrity": "sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^10.1.3",
|
||||
"@octokit/request-error": "^6.1.7",
|
||||
"@octokit/types": "^13.6.2",
|
||||
"fast-content-type-parse": "^2.0.0",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"@octokit/rest": {
|
||||
"version": "18.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz",
|
||||
"integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==",
|
||||
"requires": {
|
||||
"@octokit/core": "^3.5.1",
|
||||
"@octokit/plugin-paginate-rest": "^2.16.8",
|
||||
"@octokit/plugin-request-log": "^1.0.4",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^5.12.0"
|
||||
"node_modules/@octokit/request-error": {
|
||||
"version": "6.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz",
|
||||
"integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"@octokit/types": {
|
||||
"node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": {
|
||||
"version": "24.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/request-error/node_modules/@octokit/types": {
|
||||
"version": "13.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^24.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request/node_modules/@octokit/openapi-types": {
|
||||
"version": "24.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/request/node_modules/@octokit/types": {
|
||||
"version": "13.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^24.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.1.tgz",
|
||||
"integrity": "sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/core": "^6.1.4",
|
||||
"@octokit/plugin-paginate-rest": "^11.4.2",
|
||||
"@octokit/plugin-request-log": "^5.3.1",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^13.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "11.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.4.2.tgz",
|
||||
"integrity": "sha512-BXJ7XPCTDXFF+wxcg/zscfgw2O/iDPtNSkwwR1W1W5c4Mb3zav/M2XvxQ23nVmKj7jpweB4g8viMeCQdm7LMVA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-request-log": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz",
|
||||
"integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "13.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.3.1.tgz",
|
||||
"integrity": "sha512-o8uOBdsyR+WR8MK9Cco8dCgvG13H1RlM1nWnK/W7TEACQBFux/vPREgKucxUfuDQ5yi1T3hGf4C5ZmZXAERgwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.8.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/types": {
|
||||
"version": "6.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.33.0.tgz",
|
||||
"integrity": "sha512-0zffZ048M0UhthyPXQHLz4038Ak46nMWZXkzlXvXB/M/L1jYPBceq4iZj4qjKVrvveaJrrgKdJ9+3yUuITfcCw==",
|
||||
"requires": {
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^11.1.0"
|
||||
}
|
||||
},
|
||||
"before-after-hook": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
|
||||
"integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ=="
|
||||
"node_modules/before-after-hook": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz",
|
||||
"integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"bottleneck": {
|
||||
"node_modules/bottleneck": {
|
||||
"version": "2.19.5",
|
||||
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
|
||||
"integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="
|
||||
},
|
||||
"deprecation": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||
"node_modules/fast-content-type-parse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz",
|
||||
"integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"requires": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
||||
},
|
||||
"universal-user-agent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
|
||||
},
|
||||
"webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
||||
"requires": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
"node_modules/universal-user-agent": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz",
|
||||
"integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==",
|
||||
"license": "ISC"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@octokit/plugin-retry": "^3.0.9",
|
||||
"@octokit/plugin-throttling": "^3.5.2",
|
||||
"@octokit/rest": "^18.12.0"
|
||||
"@octokit/plugin-throttling": "^9.6.0",
|
||||
"@octokit/rest": "^21.1.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,38 +42,40 @@ echo INSTALLDIR=%INSTALLDIR%
|
||||
|
||||
cd "%BUILDDIR%"
|
||||
|
||||
set FREETYPE=2.13.2
|
||||
set HARFBUZZ=8.3.1
|
||||
set LIBJPEG=9f
|
||||
set LIBPNG=1643
|
||||
set FREETYPE=2.13.3
|
||||
set HARFBUZZ=10.0.1
|
||||
set LIBJPEGTURBO=3.1.0
|
||||
set LIBPNG=1645
|
||||
set LZ4=b8fd2d15309dd4e605070bd4486e26b6ef814e29
|
||||
set QT=6.7.0
|
||||
set QTMINOR=6.7
|
||||
set SDL=SDL2-2.30.2
|
||||
set WEBP=1.3.2
|
||||
set SDL=SDL3-3.2.10
|
||||
set QT=6.9.0
|
||||
set QTMINOR=6.9
|
||||
set WEBP=1.5.0
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set ZSTD=1.5.5
|
||||
set ZSTD=1.5.7
|
||||
set KDDOCKWIDGETS=2.2.3
|
||||
|
||||
set SHADERC=2024.1
|
||||
set SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
|
||||
set SHADERC_SPIRVHEADERS=5e3ad389ee56fca27c9705d093ae5387ce404df4
|
||||
set SHADERC_SPIRVTOOLS=dd4b663e13c07fea4fbb3f70c1c91c86731099f7
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 1ac27e16c134a7f2ccea177faba19801131116fd682efc1f5737037c5db224b5 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip b2bc56184ae37324bc4829fde7d3f9e6916866ad711ee85792e457547c9fd127 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1643.zip fc466a1e638e635d6c66363bdf3f38555b81b0141d0b06ba45b49ccca327436d || goto error
|
||||
call :downloadfile "jpegsr%LIBJPEG%.zip" https://ijg.org/files/jpegsr%LIBJPEG%.zip 6255da8c89e09d694e6800688c76145eb6870a76ac0d36c74fccd61b3940aafa || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 2a499607df669e40258e53d0ade8035ba4ec0175244869d1025d460562aa09b4 || goto error
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 8adf9f5a4b6022aa2744f45c89ce347df46fea8403e99f01d650b11c417d0aa8 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1645.zip a66c4b1350b67776e90263e2550933067cd9ccbd318db489f84dcc0d2b033249 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/%LZ4%.zip" 0c33119688d6b180c7e760b0acd70059222389cfd581632623784bee27e51a31 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" c5d78a9e0346c6695f03df8ba25e5e111a1e23c8aefa8372a1c5a0dd79acaf10 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 3027fb990cb66436b5476b9dd17cd58f23b55a42eb1c1bcf9c7d78bca3ad7d63 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" f30065289517847d721467827ee446a5f606f6d1c750e166cbfb0ed5bf066c5e || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 882d1db58d35155bd92e4ed92b485d7d713b6aff0d7cf78655de0b414a980689 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 93a31892ca8a4f38464e923328788ce3da881d82016fe18fa1ed12dd43ce486c || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 102ca62fa682c0d3e700ba89069fd3b6663b9f0c2890b058e97998b6e8971fb3 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 01d9ab20fc071b076be91df5396b464b4ef159e93b2b2addda1cc36750fc1f29 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 513df15a6365a40f6230ec9463ad8c71b824e181d4b661dac9707e103b24ae0c || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" d428fd17a0d3f92c48a30f1d23806bf20352fbce2e80e5bbee27fa80576480ee || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 54bf06afeb67035f1c6afcd00beec755c0d776626b4cce9ab56992a55215ba69 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 5f8a94a161bd2e71a82f478dc19f4ec77ac95a50709f5a68d5951001ed6bb856 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 5885ce1a114615cc5fa69e459f069d3fe2bcb1320fd9cc162821f3920ef44735 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" c5c8daa1d40dabc51790c62a5b86af2b36dfc4e1a738ff10dc4a46ea4e68ee51 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 1ba8e5b48f3b4d47d2de7121529d448532200fa36d9ed21f93909f6eb03f61cb || goto error
|
||||
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 6c9f42ed6bf42750f5369b089909abfdcf0101488b4a1f41116d5159d00af8e7 || goto error
|
||||
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 03ad8a6fa987af4653d0cfe6bdaed41bcf617f1366a151fb1574da75950cd3e8 || goto error
|
||||
@@ -107,10 +109,10 @@ cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
echo Building libjpeg...
|
||||
%SEVENZIP% x "jpegsr%LIBJPEG%.zip" || goto error
|
||||
cd "jpeg-%LIBJPEG%" || goto error
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\libjpeg-cmake.patch" || goto error
|
||||
echo Building libjpegturbo...
|
||||
rmdir /S /Q "libjpeg-turbo-%LIBJPEGTURBO%"
|
||||
tar -xf "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" || goto error
|
||||
cd "libjpeg-turbo-%LIBJPEGTURBO%" || goto error
|
||||
cmake %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DBUILD_STATIC_LIBS=OFF -B build -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
@@ -155,7 +157,7 @@ cd .. || goto error
|
||||
|
||||
echo Building Zstandard...
|
||||
rmdir /S /Q "zstd-%ZSTD%"
|
||||
%SEVENZIP% x "-x^!zstd-1.5.5\tests\cli-tests\bin" "zstd-%ZSTD%.zip" || goto error
|
||||
%SEVENZIP% x "-x^!zstd-%ZSTD%\tests\cli-tests\bin" "zstd-%ZSTD%.zip" || goto error
|
||||
cd "zstd-%ZSTD%"
|
||||
cmake %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DZSTD_BUILD_SHARED=ON -DZSTD_BUILD_STATIC=OFF -DZSTD_BUILD_PROGRAMS=OFF -B build -G Ninja build/cmake
|
||||
cmake --build build --parallel || goto error
|
||||
@@ -178,7 +180,7 @@ cd "%SDL%" || goto error
|
||||
cmake -B build %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release %FORCEPDB% -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
copy build\SDL2.pdb "%INSTALLDIR%\bin" || goto error
|
||||
copy build\SDL3.pdb "%INSTALLDIR%\bin" || goto error
|
||||
cd .. || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
@@ -240,6 +242,16 @@ cmake --build . --parallel || goto error
|
||||
ninja install || goto error
|
||||
cd ..\.. || goto error
|
||||
|
||||
echo "Building KDDockWidgets..."
|
||||
rmdir /S /Q "KDDockWidgets-%KDDOCKWIDGETS%"
|
||||
%SEVENZIP% x "KDDockWidgets-%KDDOCKWIDGETS%.zip" || goto error
|
||||
cd "KDDockWidgets-%KDDOCKWIDGETS%" || goto error
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\..\common\kddockwidgets-dodgy-include.patch" || goto error
|
||||
cmake %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
echo Building shaderc...
|
||||
rmdir /S /Q "shaderc-%SHADERC%"
|
||||
%SEVENZIP% x "shaderc-%SHADERC%.zip" || goto error
|
||||
|
||||
@@ -40,39 +40,40 @@ set "PATH=%PATH%;%INSTALLDIR%\bin"
|
||||
|
||||
cd "%BUILDDIR%"
|
||||
|
||||
set FREETYPE=2.13.2
|
||||
set HARFBUZZ=8.3.1
|
||||
set LIBJPEG=9f
|
||||
set LIBPNG=1643
|
||||
set FREETYPE=2.13.3
|
||||
set HARFBUZZ=10.0.1
|
||||
set LIBJPEGTURBO=3.1.0
|
||||
set LIBPNG=1645
|
||||
set LZ4=b8fd2d15309dd4e605070bd4486e26b6ef814e29
|
||||
set QT=6.7.2
|
||||
set QTMINOR=6.7
|
||||
set SDL=SDL2-2.30.5
|
||||
set WEBP=1.4.0
|
||||
set SDL=SDL3-3.2.10
|
||||
set QT=6.9.0
|
||||
set QTMINOR=6.9
|
||||
set WEBP=1.5.0
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set ZSTD=1.5.6
|
||||
set ZSTD=1.5.7
|
||||
set KDDOCKWIDGETS=2.2.3
|
||||
|
||||
set SHADERC=2024.1
|
||||
set SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
|
||||
set SHADERC_SPIRVHEADERS=5e3ad389ee56fca27c9705d093ae5387ce404df4
|
||||
set SHADERC_SPIRVTOOLS=dd4b663e13c07fea4fbb3f70c1c91c86731099f7
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 1ac27e16c134a7f2ccea177faba19801131116fd682efc1f5737037c5db224b5 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip b2bc56184ae37324bc4829fde7d3f9e6916866ad711ee85792e457547c9fd127 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1643.zip fc466a1e638e635d6c66363bdf3f38555b81b0141d0b06ba45b49ccca327436d || goto error
|
||||
call :downloadfile "jpegsr%LIBJPEG%.zip" https://ijg.org/files/jpegsr%LIBJPEG%.zip 6255da8c89e09d694e6800688c76145eb6870a76ac0d36c74fccd61b3940aafa || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 61f873ec69e3be1b99535634340d5bde750b2e4447caa1db9f61be3fd49ab1e5 || goto error
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 8adf9f5a4b6022aa2744f45c89ce347df46fea8403e99f01d650b11c417d0aa8 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1645.zip a66c4b1350b67776e90263e2550933067cd9ccbd318db489f84dcc0d2b033249 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/%LZ4%.zip" 0c33119688d6b180c7e760b0acd70059222389cfd581632623784bee27e51a31 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 688d3da2bf7e887d0ba8e0f81c926119f85029544f4f6da8dea96db70f9d28e3 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 488119aad60719a085a1e45c31641ac2406ef86fc088a3c99885c18e9d6b4bb9 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 8e736b02db7dd67dbe834d56503b242344ce85d3532da692f1812b30ccf80997 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 85a22142270a92be0dd0ab5d27cc53617b2a2f1a45fc0a3890024164032f8475 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 9e15f1fdbd83e4123e733bff20aff1b45921c09056c3790fa42eb71d0a5cd01f || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" d1f25e0f68a1282feffdd5fe795a027ee5f16ad19e3b1fa2e04a51cea19110ec || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 01d9ab20fc071b076be91df5396b464b4ef159e93b2b2addda1cc36750fc1f29 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 513df15a6365a40f6230ec9463ad8c71b824e181d4b661dac9707e103b24ae0c || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" d428fd17a0d3f92c48a30f1d23806bf20352fbce2e80e5bbee27fa80576480ee || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 54bf06afeb67035f1c6afcd00beec755c0d776626b4cce9ab56992a55215ba69 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 5f8a94a161bd2e71a82f478dc19f4ec77ac95a50709f5a68d5951001ed6bb856 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 5885ce1a114615cc5fa69e459f069d3fe2bcb1320fd9cc162821f3920ef44735 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 3b1c3b46e416d36931efd34663122d7f51b550c87f74de2d38249516fe7d8be5 || goto error
|
||||
call :downloadfile "zstd-fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch" https://github.com/facebook/zstd/commit/fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch 675f144b11f8ab2424b64bed8ccdca5d3f35b9326046fa7a883925dd180f0651 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 1ba8e5b48f3b4d47d2de7121529d448532200fa36d9ed21f93909f6eb03f61cb || goto error
|
||||
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 6c9f42ed6bf42750f5369b089909abfdcf0101488b4a1f41116d5159d00af8e7 || goto error
|
||||
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 03ad8a6fa987af4653d0cfe6bdaed41bcf617f1366a151fb1574da75950cd3e8 || goto error
|
||||
@@ -105,11 +106,10 @@ cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
echo Building libjpeg...
|
||||
rmdir /S /Q "jpeg-%LIBJPEG%"
|
||||
%SEVENZIP% x "jpegsr%LIBJPEG%.zip" || goto error
|
||||
cd "jpeg-%LIBJPEG%" || goto error
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\libjpeg-cmake.patch" || goto error
|
||||
echo Building libjpegturbo...
|
||||
rmdir /S /Q "libjpeg-turbo-%LIBJPEGTURBO%"
|
||||
tar -xf "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" || goto error
|
||||
cd "libjpeg-turbo-%LIBJPEGTURBO%" || goto error
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DBUILD_STATIC_LIBS=OFF -B build -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
@@ -154,9 +154,8 @@ cd .. || goto error
|
||||
|
||||
echo Building Zstandard...
|
||||
rmdir /S /Q "zstd-%ZSTD%"
|
||||
%SEVENZIP% x "-x^!zstd-1.5.6\tests\cli-tests\bin" "zstd-%ZSTD%.zip" || goto error
|
||||
%SEVENZIP% x "-x^!zstd-%ZSTD%\tests\cli-tests\bin" "zstd-%ZSTD%.zip" || goto error
|
||||
cd "zstd-%ZSTD%"
|
||||
%PATCH% -p1 < "..\zstd-fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch" || goto error
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DZSTD_BUILD_SHARED=ON -DZSTD_BUILD_STATIC=OFF -DZSTD_BUILD_PROGRAMS=OFF -B build -G Ninja build/cmake
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
@@ -178,7 +177,7 @@ cd "%SDL%" || goto error
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release %FORCEPDB% -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
copy build\SDL2.pdb "%INSTALLDIR%\bin" || goto error
|
||||
copy build\SDL3.pdb "%INSTALLDIR%\bin" || goto error
|
||||
cd .. || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
@@ -195,6 +194,9 @@ cd "qtbase-everywhere-src-%QT%" || goto error
|
||||
rem Disable the PCRE2 JIT, it doesn't properly verify AVX2 support.
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\qtbase-disable-pcre2-jit.patch" || goto error
|
||||
|
||||
rem Hackfix settings icon stretching
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\qtbase-fix-icon-stretch.patch" || goto error
|
||||
|
||||
cmake -B build -DFEATURE_sql=OFF -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" %FORCEPDB% -DINPUT_gui=yes -DINPUT_widgets=yes -DINPUT_ssl=yes -DINPUT_openssl=no -DINPUT_schannel=yes -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON %QTBUILDSPEC% || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
@@ -244,6 +246,16 @@ cmake --build . --parallel || goto error
|
||||
ninja install || goto error
|
||||
cd ..\.. || goto error
|
||||
|
||||
echo "Building KDDockWidgets..."
|
||||
rmdir /S /Q "KDDockWidgets-%KDDOCKWIDGETS%"
|
||||
%SEVENZIP% x "KDDockWidgets-%KDDOCKWIDGETS%.zip" || goto error
|
||||
cd "KDDockWidgets-%KDDOCKWIDGETS%" || goto error
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\..\common\kddockwidgets-dodgy-include.patch" || goto error
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
echo Building shaderc...
|
||||
rmdir /S /Q "shaderc-%SHADERC%"
|
||||
%SEVENZIP% x "shaderc-%SHADERC%.zip" || goto error
|
||||
|
||||
68
.github/workflows/scripts/windows/build-gammaray.bat
vendored
Normal file
68
.github/workflows/scripts/windows/build-gammaray.bat
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
echo Setting environment...
|
||||
if exist "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" (
|
||||
call "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
) else if exist "%ProgramFiles%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" (
|
||||
call "%ProgramFiles%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
) else (
|
||||
echo Visual Studio 2022 not found.
|
||||
goto error
|
||||
)
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
cd ..\..\..\..
|
||||
cd deps || goto error
|
||||
set "DEPSDIR=%CD%"
|
||||
cd ..
|
||||
mkdir gammaray
|
||||
cd gammaray || goto error
|
||||
set "INSTALLDIR=%CD%"
|
||||
cd ..
|
||||
mkdir gammaray-build
|
||||
cd gammaray-build || goto error
|
||||
set "BUILDDIR=%CD%"
|
||||
|
||||
echo DEPSDIR=%DEPSDIR%
|
||||
echo BUILDDIR=%BUILDDIR%
|
||||
echo INSTALLDIR=%INSTALLDIR%
|
||||
|
||||
set GAMMARAY="master"
|
||||
|
||||
echo Downloading...
|
||||
curl -L -o "GammaRay-%GAMMARAY%.tar.gz" "https://github.com/KDAB/GammaRay/archive/%GAMMARAY%.tar.gz" || goto error
|
||||
|
||||
rmdir /s /q "GammaRay-%GAMMARAY%"
|
||||
|
||||
echo Extracting...
|
||||
tar -xf "GammaRay-%GAMMARAY%.tar.gz" || goto error
|
||||
|
||||
echo Configuring...
|
||||
cmake "GammaRay-%GAMMARAY%" -B build -DCMAKE_PREFIX_PATH="%DEPSDIR%" -G Ninja -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DGAMMARAY_BUILD_DOCS=false || goto error
|
||||
|
||||
echo Building...
|
||||
cmake --build build --parallel || goto error
|
||||
|
||||
echo Installing...
|
||||
cmake --build build --target install || goto errorlevel
|
||||
|
||||
echo Copying DLLs...
|
||||
xcopy /y "%DEPSDIR%\bin\*.dll" "%INSTALLDIR%\bin\"
|
||||
xcopy /y /e /s "%DEPSDIR%\plugins" "%INSTALLDIR%\bin\"
|
||||
|
||||
echo Cleaning up...
|
||||
cd ..
|
||||
rd /s /q gammaray-build
|
||||
|
||||
echo Exiting with success.
|
||||
popd
|
||||
pause
|
||||
exit 0
|
||||
|
||||
:error
|
||||
echo Failed with error #%errorlevel%.
|
||||
popd
|
||||
pause
|
||||
exit %errorlevel%
|
||||
@@ -1,422 +0,0 @@
|
||||
diff -ruN jpeg-9f/CMakeLists.txt jpeg-9f-new/CMakeLists.txt
|
||||
--- jpeg-9f/CMakeLists.txt 1970-01-01 10:00:00.000000000 +1000
|
||||
+++ jpeg-9f-new/CMakeLists.txt 2024-03-23 21:29:37.969221600 +1000
|
||||
@@ -0,0 +1,110 @@
|
||||
+# CMake configuration for IJG libjpeg
|
||||
+# Modified from https://github.com/csparker247/jpeg-cmake/blob/develop/resources/CMakeLists.txt
|
||||
+# To install, copy this file and jconfig.h.in into a libjpeg source directory
|
||||
+# Adapted from LuaDist's CMakeLists
|
||||
+# https://github.com/LuaDist/libjpeg/blob/master/CMakeLists.txt
|
||||
+
|
||||
+cmake_minimum_required(VERSION 3.5)
|
||||
+
|
||||
+### Setup the project ###
|
||||
+file(READ "configure.ac" ac)
|
||||
+string(REGEX MATCH "AC_INIT\\(\\[libjpeg\\],\ \\[([0-9]*\\.[0-9]*\\.[0-9]*)\\]\\)" _ ${ac})
|
||||
+set(version ${CMAKE_MATCH_1})
|
||||
+project(libjpeg VERSION ${version} LANGUAGES C)
|
||||
+set(C_STANDARD 99)
|
||||
+
|
||||
+### Include extra packages ###
|
||||
+include(CMakeDependentOption)
|
||||
+include(GNUInstallDirs)
|
||||
+
|
||||
+### Options ###
|
||||
+option(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||
+option(BUILD_STATIC_LIBS "Build static libraries" ON)
|
||||
+
|
||||
+# Make sure we build at least one library
|
||||
+if(NOT(BUILD_SHARED_LIBS OR BUILD_STATIC_LIBS))
|
||||
+ message(FATAL_ERROR "Both static and shared libraries are disabled. Nothing will be built.")
|
||||
+endif()
|
||||
+
|
||||
+### Configure jconfig.h ###
|
||||
+include(ConfigureJConfig.cmake)
|
||||
+
|
||||
+### Build the object library ###
|
||||
+set(PUBLIC_HDRS
|
||||
+ jconfig.h
|
||||
+ jerror.h
|
||||
+ jmorecfg.h
|
||||
+ jpeglib.h
|
||||
+)
|
||||
+
|
||||
+set(SRCS
|
||||
+ jaricom.c jcapimin.c jcapistd.c jcarith.c jccoefct.c jccolor.c
|
||||
+ jcdctmgr.c jchuff.c jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c
|
||||
+ jcparam.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c jdarith.c
|
||||
+ jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c jdinput.c
|
||||
+ jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdpostct.c jdsample.c jdtrans.c
|
||||
+ jerror.c jfdctflt.c jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c
|
||||
+ jmemmgr.c jmemnobs.c jquant1.c jquant2.c jutils.c
|
||||
+)
|
||||
+
|
||||
+### Create static and shared libs ###
|
||||
+if(BUILD_SHARED_LIBS)
|
||||
+ add_library(libjpeg SHARED ${SRCS})
|
||||
+ target_compile_definitions(libjpeg PRIVATE COMPILING_LIBJPEG)
|
||||
+ target_include_directories(libjpeg
|
||||
+ PUBLIC
|
||||
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
+ $<INSTALL_INTERFACE:include>
|
||||
+ )
|
||||
+ set_target_properties(libjpeg
|
||||
+ PROPERTIES
|
||||
+ VERSION ${PROJECT_VERSION_MAJOR}
|
||||
+ POSITION_INDEPENDENT_CODE ON
|
||||
+ CLEAN_DIRECT_OUTPUT ON
|
||||
+ PUBLIC_HEADER "${PUBLIC_HDRS}"
|
||||
+ )
|
||||
+ install(TARGETS libjpeg
|
||||
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
+ PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
+ )
|
||||
+endif()
|
||||
+
|
||||
+if(BUILD_STATIC_LIBS)
|
||||
+ add_library(libjpeg_static STATIC $<TARGET_OBJECTS:jpeg_objs>)
|
||||
+ target_include_directories(libjpeg_static
|
||||
+ PUBLIC
|
||||
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
+ $<INSTALL_INTERFACE:include>
|
||||
+ )
|
||||
+ set_target_properties(libjpeg_static
|
||||
+ PROPERTIES
|
||||
+ OUTPUT_NAME jpeg
|
||||
+ VERSION ${PROJECT_VERSION_MAJOR}
|
||||
+ POSITION_INDEPENDENT_CODE ON
|
||||
+ CLEAN_DIRECT_OUTPUT ON
|
||||
+ PUBLIC_HEADER "${PUBLIC_HDRS}"
|
||||
+ )
|
||||
+ install(TARGETS libjpeg_static
|
||||
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
+ PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
+ )
|
||||
+endif()
|
||||
+
|
||||
+# Configure and install pkg-config and libtool files
|
||||
+if(BUILD_STATIC_LIBS OR BUILD_SHARED_LIBS)
|
||||
+ # Compute the la file's weird version number
|
||||
+ math(EXPR JPEG_CONF_VER_MAJOR "${PROJECT_VERSION_MAJOR} + ${PROJECT_VERSION_MINOR}")
|
||||
+ set(JPEG_LIB_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
|
||||
+ set(JPEG_LIB_VERSION_MINOR ${PROJECT_VERSION_MINOR})
|
||||
+
|
||||
+ # Configure and install
|
||||
+ configure_file(libjpeg.pc.cmakein libjpeg.pc @ONLY)
|
||||
+ install(FILES
|
||||
+ ${CMAKE_CURRENT_BINARY_DIR}/libjpeg.pc
|
||||
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig
|
||||
+ )
|
||||
+endif()
|
||||
+
|
||||
diff -ruN jpeg-9f/ConfigureJConfig.cmake jpeg-9f-new/ConfigureJConfig.cmake
|
||||
--- jpeg-9f/ConfigureJConfig.cmake 1970-01-01 10:00:00.000000000 +1000
|
||||
+++ jpeg-9f-new/ConfigureJConfig.cmake 2024-03-23 21:09:37.223882900 +1000
|
||||
@@ -0,0 +1,95 @@
|
||||
+include(CheckIncludeFile)
|
||||
+include(CheckSymbolExists)
|
||||
+include(CheckTypeSize)
|
||||
+
|
||||
+# Define this if your system has an ANSI-conforming <stddef.h> file.
|
||||
+check_include_file(stddef.h HAVE_STDDEF_H)
|
||||
+
|
||||
+# Define this if your system has an ANSI-conforming <stdlib.h> file.
|
||||
+check_include_file(stdlib.h HAVE_STDLIB_H)
|
||||
+
|
||||
+# Does your compiler support function prototypes?
|
||||
+# (If not, you also need to use ansi2knr, see install.txt)
|
||||
+set(HAVE_PROTOTYPES true CACHE BOOL "Does your compiler support function prototypes?")
|
||||
+
|
||||
+# Does your compiler support the declaration "unsigned char" ?
|
||||
+# How about "unsigned short" ?
|
||||
+check_type_size("unsigned char" UNSIGNED_CHAR LANGUAGE C)
|
||||
+check_type_size("unsigned short" UNSIGNED_SHORT LANGUAGE C)
|
||||
+
|
||||
+# Define "void" as "char" if your compiler doesn't know about type void.
|
||||
+# NOTE: be sure to define void such that "void *" represents the most general
|
||||
+# pointer type, e.g., that returned by malloc().
|
||||
+# NOT IMPLEMENTED: Modify in jconfig.h.in #
|
||||
+
|
||||
+# Define "const" as empty if your compiler doesn't know the "const" keyword.
|
||||
+# NOT IMPLEMENTED: Modify in jconfig.h.in #
|
||||
+
|
||||
+# Define this if an ordinary "char" type is unsigned.
|
||||
+# If you're not sure, leaving it undefined will work at some cost in speed.
|
||||
+# If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal.
|
||||
+set(CHAR_IS_UNSIGNED false CACHE BOOL "char type is unsigned")
|
||||
+
|
||||
+# Define this if your system does not have an ANSI/SysV <string.h>,
|
||||
+# but does have a BSD-style <strings.h>.
|
||||
+set(NEED_BSD_STRINGS false CACHE BOOL "Use BSD <strings.h>. Use only if system lacks ANSI/SysV <strings.h>")
|
||||
+
|
||||
+# Define this if your system does not provide typedef size_t in any of the
|
||||
+# ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in
|
||||
+# <sys/types.h> instead.
|
||||
+set(NEED_SYS_TYPES_H false CACHE BOOL "size_t defined in <sys/types.h>")
|
||||
+
|
||||
+# For 80x86 machines, you need to define NEED_FAR_POINTERS,
|
||||
+# unless you are using a large-data memory model or 80386 flat-memory mode.
|
||||
+# On less brain-damaged CPUs this symbol must not be defined.
|
||||
+# (Defining this symbol causes large data structures to be referenced through
|
||||
+# "far" pointers and to be allocated with a special version of malloc.)
|
||||
+set(NEED_FAR_POINTERS false CACHE BOOL "Reference large data structures through 'far' pointers allocated with a special version of malloc")
|
||||
+
|
||||
+# Define this if your linker needs global names to be unique in less
|
||||
+# than the first 15 characters.
|
||||
+set(NEED_SHORT_EXTERNAL_NAMES false CACHE BOOL "Global names must be unique in less than the first 15 characters")
|
||||
+
|
||||
+# Although a real ANSI C compiler can deal perfectly well with pointers to
|
||||
+# unspecified structures (see "incomplete types" in the spec), a few pre-ANSI
|
||||
+# and pseudo-ANSI compilers get confused. To keep one of these bozos happy,
|
||||
+# define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you
|
||||
+# actually get "missing structure definition" warnings or errors while
|
||||
+# compiling the JPEG code.
|
||||
+set(INCOMPLETE_TYPES_BROKEN false CACHE BOOL "Disable pointers to unspecified structures")
|
||||
+
|
||||
+# Define "boolean" as unsigned char, not enum, on Windows systems.
|
||||
+# NOT IMPLEMENTED: Modify in jconfig.h.in #
|
||||
+
|
||||
+# The following options affect code selection within the JPEG library,
|
||||
+# but they don't need to be visible to applications using the library.
|
||||
+# To minimize application namespace pollution, the symbols won't be
|
||||
+# defined unless JPEG_INTERNALS has been defined.
|
||||
+#
|
||||
+
|
||||
+# Define this if your compiler implements ">>" on signed values as a logical
|
||||
+# (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift,
|
||||
+# which is the normal and rational definition.
|
||||
+set(RIGHT_SHIFT_IS_UNSIGNED false CACHE BOOL "Compiler implements >> on signed values as a logical (unsigned) shift")
|
||||
+
|
||||
+# The remaining options do not affect the JPEG library proper,
|
||||
+# but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c).
|
||||
+# Other applications can ignore these.
|
||||
+#
|
||||
+
|
||||
+mark_as_advanced(FORCE
|
||||
+ HAVE_PROTOTYPES
|
||||
+ HAVE_UNSIGNED_CHAR
|
||||
+ HAVE_UNSIGNED_SHORT
|
||||
+ CHAR_IS_UNSIGNED
|
||||
+ HAVE_STDDEF_H
|
||||
+ HAVE_STDLIB_H
|
||||
+ NEED_BSD_STRINGS
|
||||
+ NEED_SYS_TYPES_H
|
||||
+ NEED_FAR_POINTERS
|
||||
+ NEED_SHORT_EXTERNAL_NAMES
|
||||
+ INCOMPLETE_TYPES_BROKEN
|
||||
+ RIGHT_SHIFT_IS_UNSIGNED
|
||||
+)
|
||||
+
|
||||
+configure_file(jconfig.h.in ${CMAKE_CURRENT_SOURCE_DIR}/jconfig.h)
|
||||
diff -ruN jpeg-9f/jconfig.h.in jpeg-9f-new/jconfig.h.in
|
||||
--- jpeg-9f/jconfig.h.in 1970-01-01 10:00:00.000000000 +1000
|
||||
+++ jpeg-9f-new/jconfig.h.in 2024-03-23 21:06:05.204994600 +1000
|
||||
@@ -0,0 +1,173 @@
|
||||
+/*
|
||||
+ * jconfig.h.in
|
||||
+ *
|
||||
+ * Copyright (C) 1991-1994, Thomas G. Lane.
|
||||
+ * Modified 2009-2013 by Guido Vollbeding.
|
||||
+ * This file is part of the Independent JPEG Group's software.
|
||||
+ * For conditions of distribution and use, see the accompanying README file.
|
||||
+ *
|
||||
+ * This file is a modification of jconfig.txt from libjpeg. In addition to
|
||||
+ * documenting the configuration options that are required to customize the
|
||||
+ * JPEG software for a particular system, it is used by jpeg-cmake to configure
|
||||
+ * jconfig.h
|
||||
+ */
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * These symbols indicate the properties of your machine or compiler.
|
||||
+ * #define the symbol if yes, #undef it if no.
|
||||
+ */
|
||||
+
|
||||
+/* Does your compiler support function prototypes?
|
||||
+ * (If not, you also need to use ansi2knr, see install.txt)
|
||||
+ */
|
||||
+#cmakedefine HAVE_PROTOTYPES
|
||||
+
|
||||
+/* Does your compiler support the declaration "unsigned char" ?
|
||||
+ * How about "unsigned short" ?
|
||||
+ */
|
||||
+#cmakedefine HAVE_UNSIGNED_CHAR
|
||||
+#cmakedefine HAVE_UNSIGNED_SHORT
|
||||
+
|
||||
+/* Define "void" as "char" if your compiler doesn't know about type void.
|
||||
+ * NOTE: be sure to define void such that "void *" represents the most general
|
||||
+ * pointer type, e.g., that returned by malloc().
|
||||
+ */
|
||||
+/* #define void char */
|
||||
+
|
||||
+/* Define "const" as empty if your compiler doesn't know the "const" keyword.
|
||||
+ */
|
||||
+/* #define const */
|
||||
+
|
||||
+/* Define this if an ordinary "char" type is unsigned.
|
||||
+ * If you're not sure, leaving it undefined will work at some cost in speed.
|
||||
+ * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal.
|
||||
+ */
|
||||
+#cmakedefine CHAR_IS_UNSIGNED
|
||||
+
|
||||
+/* Define this if your system has an ANSI-conforming <stddef.h> file.
|
||||
+ */
|
||||
+#cmakedefine HAVE_STDDEF_H
|
||||
+
|
||||
+/* Define this if your system has an ANSI-conforming <stdlib.h> file.
|
||||
+ */
|
||||
+#cmakedefine HAVE_STDLIB_H
|
||||
+
|
||||
+/* Define this if your system does not have an ANSI/SysV <string.h>,
|
||||
+ * but does have a BSD-style <strings.h>.
|
||||
+ */
|
||||
+#cmakedefine NEED_BSD_STRINGS
|
||||
+
|
||||
+/* Define this if your system does not provide typedef size_t in any of the
|
||||
+ * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in
|
||||
+ * <sys/types.h> instead.
|
||||
+ */
|
||||
+#cmakedefine NEED_SYS_TYPES_H
|
||||
+
|
||||
+/* For 80x86 machines, you need to define NEED_FAR_POINTERS,
|
||||
+ * unless you are using a large-data memory model or 80386 flat-memory mode.
|
||||
+ * On less brain-damaged CPUs this symbol must not be defined.
|
||||
+ * (Defining this symbol causes large data structures to be referenced through
|
||||
+ * "far" pointers and to be allocated with a special version of malloc.)
|
||||
+ */
|
||||
+#cmakedefine NEED_FAR_POINTERS
|
||||
+
|
||||
+/* Define this if your linker needs global names to be unique in less
|
||||
+ * than the first 15 characters.
|
||||
+ */
|
||||
+#cmakedefine NEED_SHORT_EXTERNAL_NAMES
|
||||
+
|
||||
+/* Although a real ANSI C compiler can deal perfectly well with pointers to
|
||||
+ * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI
|
||||
+ * and pseudo-ANSI compilers get confused. To keep one of these bozos happy,
|
||||
+ * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you
|
||||
+ * actually get "missing structure definition" warnings or errors while
|
||||
+ * compiling the JPEG code.
|
||||
+ */
|
||||
+#cmakedefine INCOMPLETE_TYPES_BROKEN
|
||||
+
|
||||
+/* Define "boolean" as unsigned char, not enum, on Windows systems.
|
||||
+ */
|
||||
+#ifdef _WIN32
|
||||
+#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
|
||||
+typedef unsigned char boolean;
|
||||
+#endif
|
||||
+#ifndef FALSE /* in case these macros already exist */
|
||||
+#define FALSE 0 /* values of boolean */
|
||||
+#endif
|
||||
+#ifndef TRUE
|
||||
+#define TRUE 1
|
||||
+#endif
|
||||
+#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * The following options affect code selection within the JPEG library,
|
||||
+ * but they don't need to be visible to applications using the library.
|
||||
+ * To minimize application namespace pollution, the symbols won't be
|
||||
+ * defined unless JPEG_INTERNALS has been defined.
|
||||
+ */
|
||||
+
|
||||
+#ifdef JPEG_INTERNALS
|
||||
+
|
||||
+/* Define this if your compiler implements ">>" on signed values as a logical
|
||||
+ * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift,
|
||||
+ * which is the normal and rational definition.
|
||||
+ */
|
||||
+#cmakedefine RIGHT_SHIFT_IS_UNSIGNED
|
||||
+
|
||||
+
|
||||
+#endif /* JPEG_INTERNALS */
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * The remaining options do not affect the JPEG library proper,
|
||||
+ * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c).
|
||||
+ * Other applications can ignore these.
|
||||
+ */
|
||||
+
|
||||
+#ifdef JPEG_CJPEG_DJPEG
|
||||
+
|
||||
+/* These defines indicate which image (non-JPEG) file formats are allowed. */
|
||||
+
|
||||
+#cmakedefine BMP_SUPPORTED /* BMP image file format */
|
||||
+#cmakedefine GIF_SUPPORTED /* GIF image file format */
|
||||
+#cmakedefine PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
|
||||
+#cmakedefine RLE_SUPPORTED /* Utah RLE image file format */
|
||||
+#cmakedefine TARGA_SUPPORTED /* Targa image file format */
|
||||
+
|
||||
+/*
|
||||
+ * This defines the default output format for djpeg. Must be one of the FMT_*
|
||||
+ * enums found in djpeg.c or djpegalt.c
|
||||
+ */
|
||||
+#cmakedefine DEFAULT_FMT @DEFAULT_FMT@
|
||||
+
|
||||
+/* Define this if you want to name both input and output files on the command
|
||||
+ * line, rather than using stdout and optionally stdin. You MUST do this if
|
||||
+ * your system can't cope with binary I/O to stdin/stdout. See comments at
|
||||
+ * head of cjpeg.c or djpeg.c.
|
||||
+ */
|
||||
+#cmakedefine TWO_FILE_COMMANDLINE
|
||||
+
|
||||
+/* Define this if your system needs explicit cleanup of temporary files.
|
||||
+ * This is crucial under MS-DOS, where the temporary "files" may be areas
|
||||
+ * of extended memory; on most other systems it's not as important.
|
||||
+ */
|
||||
+#cmakedefine NEED_SIGNAL_CATCHER
|
||||
+
|
||||
+/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb").
|
||||
+ * This is necessary on systems that distinguish text files from binary files,
|
||||
+ * and is harmless on most systems that don't. If you have one of the rare
|
||||
+ * systems that complains about the "b" spec, define this symbol.
|
||||
+ */
|
||||
+#cmakedefine DONT_USE_B_MODE
|
||||
+
|
||||
+/* Define this if you want percent-done progress reports from cjpeg/djpeg.
|
||||
+ */
|
||||
+#cmakedefine PROGRESS_REPORT
|
||||
+
|
||||
+/* Define this if you *don't* want overwrite confirmation */
|
||||
+#cmakedefine NO_OVERWRITE_CHECK
|
||||
+
|
||||
+#endif /* JPEG_CJPEG_DJPEG */
|
||||
diff -ruN jpeg-9f/jmorecfg.h jpeg-9f-new/jmorecfg.h
|
||||
--- jpeg-9f/jmorecfg.h 2022-03-31 19:41:26.000000000 +1000
|
||||
+++ jpeg-9f-new/jmorecfg.h 2024-03-23 21:20:25.514814400 +1000
|
||||
@@ -244,8 +244,13 @@
|
||||
#define LOCAL(type) static type
|
||||
/* a function referenced thru EXTERNs: */
|
||||
#define GLOBAL(type) type
|
||||
+
|
||||
/* a reference to a GLOBAL function: */
|
||||
-#define EXTERN(type) extern type
|
||||
+#ifdef COMPILING_LIBJPEG
|
||||
+#define EXTERN(type) __declspec(dllexport) extern type
|
||||
+#else
|
||||
+#define EXTERN(type) __declspec(dllimport) extern type
|
||||
+#endif
|
||||
|
||||
|
||||
/* This macro is used to declare a "method", that is, a function pointer.
|
||||
diff -ruN jpeg-9f/libjpeg.pc.cmakein jpeg-9f-new/libjpeg.pc.cmakein
|
||||
--- jpeg-9f/libjpeg.pc.cmakein 1970-01-01 10:00:00.000000000 +1000
|
||||
+++ jpeg-9f-new/libjpeg.pc.cmakein 2024-03-23 21:06:13.922695100 +1000
|
||||
@@ -0,0 +1,10 @@
|
||||
+prefix=@CMAKE_INSTALL_PREFIX@
|
||||
+exec_prefix=${prefix}
|
||||
+libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
+includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
+
|
||||
+Name: libjpeg
|
||||
+Description: Reads and writes JPEG files
|
||||
+Version: @JPEG_LIB_VERSION_MAJOR@.@JPEG_LIB_VERSION_MINOR@.0
|
||||
+Libs: -L${libdir} -ljpeg
|
||||
+Cflags: -I${includedir}
|
||||
13
.github/workflows/scripts/windows/qtbase-fix-icon-stretch.patch
vendored
Normal file
13
.github/workflows/scripts/windows/qtbase-fix-icon-stretch.patch
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
diff --git a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
|
||||
index 208420d7e8..26ef6f31ef 100644
|
||||
--- a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
|
||||
+++ b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
|
||||
@@ -4232,8 +4232,6 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption
|
||||
|
||||
case SE_ItemViewItemDecoration:
|
||||
rect = QWindowsStyle::subElementRect(element, option, widget);
|
||||
- if (qstyleoption_cast<const QStyleOptionViewItem *>(option))
|
||||
- rect.adjust(-2, 0, 2, 0);
|
||||
break;
|
||||
|
||||
case SE_ItemViewItemFocusRect:
|
||||
2
.github/workflows/triage_pr.yml
vendored
2
.github/workflows/triage_pr.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- uses: xTVaser/first-interaction@v1.2.4
|
||||
- uses: xTVaser/first-interaction@d62d6eb3c1215eae9f9d6dbfabf12d6725834cb3
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
debug-mode: false
|
||||
|
||||
2
.github/workflows/windows_build_matrix.yml
vendored
2
.github/workflows/windows_build_matrix.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
lint_vs_proj_files:
|
||||
name: Lint VS Project Files
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
runs-on: windows-2019
|
||||
runs-on: windows-2025
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
51
.github/workflows/windows_build_qt.yml
vendored
51
.github/workflows/windows_build_qt.yml
vendored
@@ -12,7 +12,7 @@ on:
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: windows-2022
|
||||
default: windows-2025
|
||||
platform:
|
||||
required: false
|
||||
type: string
|
||||
@@ -55,13 +55,31 @@ jobs:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
|
||||
steps:
|
||||
- name: Tempfix Clang
|
||||
if: inputs.configuration == 'CMake'
|
||||
run: choco uninstall llvm
|
||||
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Configure MSBuild Clang Version
|
||||
if: inputs.configuration != 'CMake'
|
||||
shell: pwsh
|
||||
run: |
|
||||
[string[]] $clang_cl = &clang-cl.exe --version
|
||||
|
||||
$version = [Regex]::Match($clang_cl[0], "(\d+\.\d+\.\d+)")
|
||||
$path = $clang_cl[3].TrimStart("InstalledDir: ").TrimEnd("\bin")
|
||||
|
||||
$output = @"
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<LLVMInstallDir>$path</LLVMInstallDir>
|
||||
<LLVMToolsVersion>$version</LLVMToolsVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
"@
|
||||
|
||||
Write-Host $output
|
||||
|
||||
$output | Out-File Directory.build.props
|
||||
|
||||
# actions/checkout elides tags, fetch them primarily for releases
|
||||
- name: Fetch Tags
|
||||
if: ${{ inputs.fetchTags }}
|
||||
@@ -100,7 +118,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: deps
|
||||
key: ${{ inputs.os }} ${{ inputs.platform }} deps ${{ hashFiles('.github/workflows/scripts/windows/build-dependencies.bat') }}
|
||||
key: ${{ inputs.os }} ${{ inputs.platform }} deps ${{ hashFiles('.github/workflows/scripts/windows/build-dependencies.bat', '.github/workflows/scripts/common/*.patch') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
@@ -149,8 +167,27 @@ jobs:
|
||||
!./bin/**/*.pdb
|
||||
!./bin/**/*.lib
|
||||
|
||||
- name: Install the Breakpad Symbol Generator
|
||||
uses: baptiste0928/cargo-install@91c5da15570085bcde6f4d7aed98cb82d6769fd3
|
||||
with:
|
||||
crate: dump_syms
|
||||
|
||||
- name: Generate Breakpad Symbols # Also flatten pdbs to a 'symbols' directory for upload-artifact
|
||||
shell: pwsh
|
||||
run: |
|
||||
mkdir -Force symbols
|
||||
Get-ChildItem -Path ./bin -Recurse -File | Where-Object {
|
||||
($_.Extension -eq ".exe" -or $_.Extension -eq ".pdb") -and ($_.Name -notmatch "updater")
|
||||
} | ForEach-Object {
|
||||
& dump_syms $_.FullName >> symbols/pcsx2-qt.bpsym
|
||||
}
|
||||
Get-ChildItem -Path ./bin -Recurse -Filter "*.pdb" | ForEach-Object {
|
||||
Copy-Item $_.FullName -Destination symbols/
|
||||
}
|
||||
|
||||
- name: Upload artifact - with symbols
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}-symbols
|
||||
path: ./bin/**/*.pdb
|
||||
path: |
|
||||
./symbols
|
||||
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -63,6 +63,7 @@ oprofile_data/
|
||||
*.kdev4
|
||||
/.kdev4*
|
||||
|
||||
# Resources and docs in /bin are tracked
|
||||
/bin/**/*.dll
|
||||
/bin/**/*.dmp
|
||||
/bin/**/*.exp
|
||||
@@ -93,6 +94,9 @@ oprofile_data/
|
||||
/bin/portable.ini
|
||||
/bin/portable.txt
|
||||
|
||||
# Resources and docs copied from /bin
|
||||
/bin-arm64
|
||||
|
||||
# Manually added by user.
|
||||
/bin/resources/patches.zip
|
||||
|
||||
@@ -105,6 +109,8 @@ oprofile_data/
|
||||
/deps-build
|
||||
/deps
|
||||
/deps-arm64
|
||||
/gammaray-build
|
||||
/gammaray
|
||||
/ipch
|
||||
|
||||
!/3rdparty/libjpeg/change.log
|
||||
@@ -115,3 +121,4 @@ oprofile_data/
|
||||
CMakeSettings.json
|
||||
/ci-artifacts/
|
||||
/out/
|
||||
/.cache/
|
||||
|
||||
41
3rdparty/ccc/CMakeLists.txt
vendored
Normal file
41
3rdparty/ccc/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(ccc)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
add_library(ccc STATIC
|
||||
src/ccc/ast.cpp
|
||||
src/ccc/ast.h
|
||||
src/ccc/elf.cpp
|
||||
src/ccc/elf.h
|
||||
src/ccc/elf_symtab.cpp
|
||||
src/ccc/elf_symtab.h
|
||||
src/ccc/importer_flags.cpp
|
||||
src/ccc/importer_flags.h
|
||||
src/ccc/mdebug_analysis.cpp
|
||||
src/ccc/mdebug_analysis.h
|
||||
src/ccc/mdebug_importer.cpp
|
||||
src/ccc/mdebug_importer.h
|
||||
src/ccc/mdebug_section.cpp
|
||||
src/ccc/mdebug_section.h
|
||||
src/ccc/mdebug_symbols.cpp
|
||||
src/ccc/mdebug_symbols.h
|
||||
src/ccc/sndll.cpp
|
||||
src/ccc/sndll.h
|
||||
src/ccc/stabs.cpp
|
||||
src/ccc/stabs.h
|
||||
src/ccc/stabs_to_ast.cpp
|
||||
src/ccc/stabs_to_ast.h
|
||||
src/ccc/symbol_database.cpp
|
||||
src/ccc/symbol_database.h
|
||||
src/ccc/symbol_file.cpp
|
||||
src/ccc/symbol_file.h
|
||||
src/ccc/symbol_table.cpp
|
||||
src/ccc/symbol_table.h
|
||||
src/ccc/util.cpp
|
||||
src/ccc/util.h
|
||||
)
|
||||
|
||||
target_include_directories(ccc PUBLIC src)
|
||||
37
3rdparty/ccc/README.md
vendored
Normal file
37
3rdparty/ccc/README.md
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# Chaos Compiler Collection
|
||||
|
||||
This code was originally developed in the following repository and was copied
|
||||
into PCSX2 by the author:
|
||||
|
||||
- [https://github.com/chaoticgd/ccc](https://github.com/chaoticgd/ccc)
|
||||
|
||||
It includes additional resources that are not present in the PCSX2 repository.
|
||||
|
||||
## Documentation
|
||||
|
||||
### DWARF (.debug) Section
|
||||
|
||||
- [DWARF Debugging Information Format](https://dwarfstd.org/doc/dwarf_1_1_0.pdf)
|
||||
|
||||
### MIPS Debug (.mdebug) Section
|
||||
|
||||
- [Third Eye Software and the MIPS symbol table (Peter Rowell)](http://datahedron.com/mips.html)
|
||||
- [MIPS Mdebug Debugging Information (David Anderson, 1996)](https://www.prevanders.net/Mdebug.ps)
|
||||
- MIPS Assembly Language Programmer's Guide, Symbol Table Chapter (Silicon Graphics, 1992)
|
||||
- Tru64 UNIX Object File and Symbol Table Format Specification, Symbol Table Chapter
|
||||
- `mdebugread.c` from gdb (reading)
|
||||
- `ecoff.c` from gas (writing)
|
||||
- `include/coff/sym.h` from binutils (headers)
|
||||
|
||||
### MIPS EABI
|
||||
|
||||
- [MIPS EABI](https://sourceware.org/legacy-ml/binutils/2003-06/msg00436.html)
|
||||
|
||||
### STABS
|
||||
|
||||
- [The "stabs" representation of debugging information (Julia Menapace, Jim Kingdon, and David MacKenzie, 1992-???)](https://sourceware.org/gdb/onlinedocs/stabs.html)
|
||||
- `stabs.c` from binutils (reading)
|
||||
- `stabsread.c` from gdb (reading)
|
||||
- `dbxread.c` from gdb (reading)
|
||||
- `dbxout.c` from gcc (writing)
|
||||
- `stab.def` from gcc (symbol codes)
|
||||
75
3rdparty/ccc/ccc.vcxproj
vendored
Normal file
75
3rdparty/ccc/ccc.vcxproj
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(SolutionDir)common\vsprops\BaseProjectConfig.props" />
|
||||
<Import Project="$(SolutionDir)common\vsprops\WinSDK.props" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{2589F8CE-EA77-4B73-911E-64074569795B}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset Condition="!$(Configuration.Contains(Clang))">$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<PlatformToolset Condition="$(Configuration.Contains(Clang))">ClangCL</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization Condition="$(Configuration.Contains(Release))">true</WholeProgramOptimization>
|
||||
<UseDebugLibraries Condition="$(Configuration.Contains(Debug))">true</UseDebugLibraries>
|
||||
<UseDebugLibraries Condition="!$(Configuration.Contains(Debug))">false</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="..\DefaultProjectRootDir.props" />
|
||||
<Import Project="..\3rdparty.props" />
|
||||
<Import Condition="$(Configuration.Contains(Debug))" Project="..\..\common\vsprops\CodeGen_Debug.props" />
|
||||
<Import Condition="$(Configuration.Contains(Devel))" Project="..\..\common\vsprops\CodeGen_Devel.props" />
|
||||
<Import Condition="$(Configuration.Contains(Release))" Project="..\..\common\vsprops\CodeGen_Release.props" />
|
||||
<Import Condition="!$(Configuration.Contains(Release))" Project="..\..\common\vsprops\IncrementalLinking.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\ccc\ast.h" />
|
||||
<ClInclude Include="src\ccc\elf.h" />
|
||||
<ClInclude Include="src\ccc\elf_symtab.h" />
|
||||
<ClInclude Include="src\ccc\importer_flags.h" />
|
||||
<ClInclude Include="src\ccc\mdebug_analysis.h" />
|
||||
<ClInclude Include="src\ccc\mdebug_importer.h" />
|
||||
<ClInclude Include="src\ccc\mdebug_section.h" />
|
||||
<ClInclude Include="src\ccc\mdebug_symbols.h" />
|
||||
<ClInclude Include="src\ccc\sndll.h" />
|
||||
<ClInclude Include="src\ccc\stabs.h" />
|
||||
<ClInclude Include="src\ccc\stabs_to_ast.h" />
|
||||
<ClInclude Include="src\ccc\symbol_database.h" />
|
||||
<ClInclude Include="src\ccc\symbol_file.h" />
|
||||
<ClInclude Include="src\ccc\symbol_table.h" />
|
||||
<ClInclude Include="src\ccc\util.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\ccc\ast.cpp" />
|
||||
<ClCompile Include="src\ccc\elf.cpp" />
|
||||
<ClCompile Include="src\ccc\elf_symtab.cpp" />
|
||||
<ClCompile Include="src\ccc\importer_flags.cpp" />
|
||||
<ClCompile Include="src\ccc\mdebug_analysis.cpp" />
|
||||
<ClCompile Include="src\ccc\mdebug_importer.cpp" />
|
||||
<ClCompile Include="src\ccc\mdebug_section.cpp" />
|
||||
<ClCompile Include="src\ccc\mdebug_symbols.cpp" />
|
||||
<ClCompile Include="src\ccc\sndll.cpp" />
|
||||
<ClCompile Include="src\ccc\stabs.cpp" />
|
||||
<ClCompile Include="src\ccc\stabs_to_ast.cpp" />
|
||||
<ClCompile Include="src\ccc\symbol_database.cpp" />
|
||||
<ClCompile Include="src\ccc\symbol_file.cpp" />
|
||||
<ClCompile Include="src\ccc\symbol_table.cpp" />
|
||||
<ClCompile Include="src\ccc\util.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
111
3rdparty/ccc/ccc.vcxproj.filters
vendored
Normal file
111
3rdparty/ccc/ccc.vcxproj.filters
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\ccc\ast.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ccc\elf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ccc\elf_symtab.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ccc\importer_flags.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ccc\mdebug_analysis.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ccc\mdebug_importer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ccc\mdebug_section.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ccc\mdebug_symbols.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ccc\sndll.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ccc\stabs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ccc\stabs_to_ast.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ccc\symbol_database.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ccc\symbol_file.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ccc\symbol_table.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ccc\util.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\ccc\ast.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ccc\elf.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ccc\elf_symtab.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ccc\importer_flags.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ccc\mdebug_analysis.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ccc\mdebug_importer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ccc\mdebug_section.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ccc\mdebug_symbols.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ccc\sndll.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ccc\stabs.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ccc\stabs_to_ast.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ccc\symbol_database.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ccc\symbol_file.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ccc\symbol_table.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ccc\util.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
562
3rdparty/ccc/src/ccc/ast.cpp
vendored
Normal file
562
3rdparty/ccc/src/ccc/ast.cpp
vendored
Normal file
@@ -0,0 +1,562 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "ast.h"
|
||||
|
||||
#include "importer_flags.h"
|
||||
#include "symbol_database.h"
|
||||
|
||||
namespace ccc::ast {
|
||||
|
||||
static bool compare_nodes_and_merge(
|
||||
CompareResult& dest, const Node& node_lhs, const Node& node_rhs, const SymbolDatabase* database);
|
||||
static bool try_to_match_wobbly_typedefs(
|
||||
const Node& node_lhs, const Node& node_rhs, const SymbolDatabase& database);
|
||||
|
||||
void Node::set_access_specifier(AccessSpecifier specifier, u32 importer_flags)
|
||||
{
|
||||
if((importer_flags & NO_ACCESS_SPECIFIERS) == 0) {
|
||||
access_specifier = specifier;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<Node*, DataType*> Node::physical_type(SymbolDatabase& database, s32 max_depth)
|
||||
{
|
||||
Node* type = this;
|
||||
DataType* symbol = nullptr;
|
||||
for(s32 i = 0; i < max_depth && type->descriptor == TYPE_NAME; i++) {
|
||||
DataType* data_type = database.data_types.symbol_from_handle(type->as<TypeName>().data_type_handle);
|
||||
if (!data_type || !data_type->type()) {
|
||||
break;
|
||||
}
|
||||
|
||||
type = data_type->type();
|
||||
symbol = data_type;
|
||||
}
|
||||
|
||||
return std::pair(type, symbol);
|
||||
}
|
||||
|
||||
std::pair<const Node*, const DataType*> Node::physical_type(const SymbolDatabase& database, s32 max_depth) const
|
||||
{
|
||||
return const_cast<Node*>(this)->physical_type(const_cast<SymbolDatabase&>(database), max_depth);
|
||||
}
|
||||
|
||||
const char* member_function_modifier_to_string(MemberFunctionModifier modifier)
|
||||
{
|
||||
switch(modifier) {
|
||||
case MemberFunctionModifier::NONE: return "none";
|
||||
case MemberFunctionModifier::STATIC: return "static";
|
||||
case MemberFunctionModifier::VIRTUAL: return "virtual";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool StructOrUnion::flatten_fields(
|
||||
std::vector<FlatField>& output,
|
||||
const DataType* symbol,
|
||||
const SymbolDatabase& database,
|
||||
bool skip_statics,
|
||||
s32 base_offset,
|
||||
s32 max_fields,
|
||||
s32 max_depth) const
|
||||
{
|
||||
if(max_depth == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(const std::unique_ptr<Node>& type_name : base_classes) {
|
||||
if(type_name->descriptor != TYPE_NAME) {
|
||||
continue;
|
||||
}
|
||||
|
||||
s32 new_base_offset = base_offset + type_name->offset_bytes;
|
||||
|
||||
DataTypeHandle handle = type_name->as<TypeName>().data_type_handle;
|
||||
const DataType* base_class_symbol = database.data_types.symbol_from_handle(handle);
|
||||
if(!base_class_symbol || !base_class_symbol->type() || base_class_symbol->type()->descriptor != STRUCT_OR_UNION) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const StructOrUnion& base_class = base_class_symbol->type()->as<StructOrUnion>();
|
||||
if(!base_class.flatten_fields(output, base_class_symbol, database, skip_statics, new_base_offset, max_fields, max_depth - 1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for(const std::unique_ptr<Node>& field : fields) {
|
||||
if(skip_statics && field->storage_class == STORAGE_CLASS_STATIC) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if((s32) output.size() >= max_fields) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FlatField& flat = output.emplace_back();
|
||||
flat.node = field.get();
|
||||
flat.symbol = symbol;
|
||||
flat.base_offset = base_offset;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* type_name_source_to_string(TypeNameSource source)
|
||||
{
|
||||
switch(source) {
|
||||
case TypeNameSource::REFERENCE: return "reference";
|
||||
case TypeNameSource::CROSS_REFERENCE: return "cross_reference";
|
||||
case TypeNameSource::UNNAMED_THIS: return "this";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char* forward_declared_type_to_string(ForwardDeclaredType type)
|
||||
{
|
||||
switch(type) {
|
||||
case ForwardDeclaredType::STRUCT: return "struct";
|
||||
case ForwardDeclaredType::UNION: return "union";
|
||||
case ForwardDeclaredType::ENUM: return "enum";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
DataTypeHandle TypeName::data_type_handle_unless_forward_declared() const
|
||||
{
|
||||
if(!is_forward_declared) {
|
||||
return data_type_handle;
|
||||
} else {
|
||||
return DataTypeHandle();
|
||||
}
|
||||
}
|
||||
|
||||
CompareResult compare_nodes(
|
||||
const Node& node_lhs, const Node& node_rhs, const SymbolDatabase* database, bool check_intrusive_fields)
|
||||
{
|
||||
CompareResult result = CompareResultType::MATCHES_NO_SWAP;
|
||||
|
||||
if(node_lhs.descriptor != node_rhs.descriptor) {
|
||||
return CompareFailReason::DESCRIPTOR;
|
||||
}
|
||||
|
||||
if(check_intrusive_fields) {
|
||||
if(node_lhs.storage_class != node_rhs.storage_class) {
|
||||
// In some cases we can determine that a type was typedef'd for C
|
||||
// translation units, but not for C++ translation units, so we need
|
||||
// to add a special case for that here.
|
||||
if(node_lhs.storage_class == STORAGE_CLASS_TYPEDEF && node_rhs.storage_class == STORAGE_CLASS_NONE) {
|
||||
result = CompareResultType::MATCHES_FAVOUR_LHS;
|
||||
} else if(node_lhs.storage_class == STORAGE_CLASS_NONE && node_rhs.storage_class == STORAGE_CLASS_TYPEDEF) {
|
||||
result = CompareResultType::MATCHES_FAVOUR_RHS;
|
||||
} else {
|
||||
return CompareFailReason::STORAGE_CLASS;
|
||||
}
|
||||
}
|
||||
|
||||
// Vtable pointers and constructors can sometimes contain type numbers
|
||||
// that are different between translation units, so we don't want to
|
||||
// compare them.
|
||||
bool is_vtable_pointer = node_lhs.is_vtable_pointer && node_rhs.is_vtable_pointer;
|
||||
bool is_numbered_constructor = node_lhs.name.starts_with("$_") && node_rhs.name.starts_with("$_");
|
||||
if(node_lhs.name != node_rhs.name && !is_vtable_pointer && !is_numbered_constructor) {
|
||||
return CompareFailReason::NAME;
|
||||
}
|
||||
|
||||
if(node_lhs.offset_bytes != node_rhs.offset_bytes) {
|
||||
return CompareFailReason::RELATIVE_OFFSET_BYTES;
|
||||
}
|
||||
|
||||
if(node_lhs.size_bits != node_rhs.size_bits) {
|
||||
return CompareFailReason::SIZE_BITS;
|
||||
}
|
||||
|
||||
if(node_lhs.is_const != node_rhs.is_const) {
|
||||
return CompareFailReason::CONSTNESS;
|
||||
}
|
||||
}
|
||||
|
||||
switch(node_lhs.descriptor) {
|
||||
case ARRAY: {
|
||||
const auto [lhs, rhs] = Node::as<Array>(node_lhs, node_rhs);
|
||||
|
||||
if(compare_nodes_and_merge(result, *lhs.element_type.get(), *rhs.element_type.get(), database)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if(lhs.element_count != rhs.element_count) {
|
||||
return CompareFailReason::ARRAY_ELEMENT_COUNT;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case BITFIELD: {
|
||||
const auto [lhs, rhs] = Node::as<BitField>(node_lhs, node_rhs);
|
||||
|
||||
if(lhs.bitfield_offset_bits != rhs.bitfield_offset_bits) {
|
||||
return CompareFailReason::BITFIELD_OFFSET_BITS;
|
||||
}
|
||||
|
||||
if(compare_nodes_and_merge(result, *lhs.underlying_type.get(), *rhs.underlying_type.get(), database)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case BUILTIN: {
|
||||
const auto [lhs, rhs] = Node::as<BuiltIn>(node_lhs, node_rhs);
|
||||
|
||||
if(lhs.bclass != rhs.bclass) {
|
||||
return CompareFailReason::BUILTIN_CLASS;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ENUM: {
|
||||
const auto [lhs, rhs] = Node::as<Enum>(node_lhs, node_rhs);
|
||||
|
||||
if(lhs.constants != rhs.constants) {
|
||||
return CompareFailReason::ENUM_CONSTANTS;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ERROR_NODE: {
|
||||
break;
|
||||
}
|
||||
case FUNCTION: {
|
||||
const auto [lhs, rhs] = Node::as<Function>(node_lhs, node_rhs);
|
||||
|
||||
if(lhs.return_type.has_value() != rhs.return_type.has_value()) {
|
||||
return CompareFailReason::FUNCTION_RETURN_TYPE_HAS_VALUE;
|
||||
}
|
||||
|
||||
if(lhs.return_type.has_value()) {
|
||||
if(compare_nodes_and_merge(result, *lhs.return_type->get(), *rhs.return_type->get(), database)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if(lhs.parameters.has_value() && rhs.parameters.has_value()) {
|
||||
if(lhs.parameters->size() != rhs.parameters->size()) {
|
||||
return CompareFailReason::FUNCTION_PARAMAETER_COUNT;
|
||||
}
|
||||
for(size_t i = 0; i < lhs.parameters->size(); i++) {
|
||||
if(compare_nodes_and_merge(result, *(*lhs.parameters)[i].get(), *(*rhs.parameters)[i].get(), database)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} else if(lhs.parameters.has_value() != rhs.parameters.has_value()) {
|
||||
return CompareFailReason::FUNCTION_PARAMETERS_HAS_VALUE;
|
||||
}
|
||||
|
||||
if(lhs.modifier != rhs.modifier) {
|
||||
return CompareFailReason::FUNCTION_MODIFIER;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case POINTER_OR_REFERENCE: {
|
||||
const auto [lhs, rhs] = Node::as<PointerOrReference>(node_lhs, node_rhs);
|
||||
|
||||
if(lhs.is_pointer != rhs.is_pointer) {
|
||||
return CompareFailReason::DESCRIPTOR;
|
||||
}
|
||||
|
||||
if(compare_nodes_and_merge(result, *lhs.value_type.get(), *rhs.value_type.get(), database)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case POINTER_TO_DATA_MEMBER: {
|
||||
const auto [lhs, rhs] = Node::as<PointerToDataMember>(node_lhs, node_rhs);
|
||||
|
||||
if(compare_nodes_and_merge(result, *lhs.class_type.get(), *rhs.class_type.get(), database)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if(compare_nodes_and_merge(result, *lhs.member_type.get(), *rhs.member_type.get(), database)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case STRUCT_OR_UNION: {
|
||||
const auto [lhs, rhs] = Node::as<StructOrUnion>(node_lhs, node_rhs);
|
||||
|
||||
if(lhs.is_struct != rhs.is_struct) {
|
||||
return CompareFailReason::DESCRIPTOR;
|
||||
}
|
||||
|
||||
if(lhs.base_classes.size() != rhs.base_classes.size()) {
|
||||
return CompareFailReason::BASE_CLASS_COUNT;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < lhs.base_classes.size(); i++) {
|
||||
if(compare_nodes_and_merge(result, *lhs.base_classes[i].get(), *rhs.base_classes[i].get(), database)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if(lhs.fields.size() != rhs.fields.size()) {
|
||||
return CompareFailReason::FIELDS_SIZE;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < lhs.fields.size(); i++) {
|
||||
if(compare_nodes_and_merge(result, *lhs.fields[i].get(), *rhs.fields[i].get(), database)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if(lhs.member_functions.size() != rhs.member_functions.size()) {
|
||||
return CompareFailReason::MEMBER_FUNCTION_COUNT;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < lhs.member_functions.size(); i++) {
|
||||
if(compare_nodes_and_merge(result, *lhs.member_functions[i].get(), *rhs.member_functions[i].get(), database)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case TYPE_NAME: {
|
||||
const auto [lhs, rhs] = Node::as<TypeName>(node_lhs, node_rhs);
|
||||
|
||||
// Don't check the source so that REFERENCE and CROSS_REFERENCE are
|
||||
// treated as the same.
|
||||
if(lhs.data_type_handle != rhs.data_type_handle) {
|
||||
return CompareFailReason::TYPE_NAME;
|
||||
}
|
||||
|
||||
const TypeName::UnresolvedStabs* lhs_unresolved_stabs = lhs.unresolved_stabs.get();
|
||||
const TypeName::UnresolvedStabs* rhs_unresolved_stabs = rhs.unresolved_stabs.get();
|
||||
if(lhs_unresolved_stabs && rhs_unresolved_stabs) {
|
||||
if(lhs_unresolved_stabs->type_name != rhs_unresolved_stabs->type_name) {
|
||||
return CompareFailReason::TYPE_NAME;
|
||||
}
|
||||
} else if(lhs_unresolved_stabs || rhs_unresolved_stabs) {
|
||||
return CompareFailReason::TYPE_NAME;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool compare_nodes_and_merge(
|
||||
CompareResult& dest, const Node& node_lhs, const Node& node_rhs, const SymbolDatabase* database)
|
||||
{
|
||||
CompareResult result = compare_nodes(node_lhs, node_rhs, database, true);
|
||||
if(database) {
|
||||
if(result.type == CompareResultType::DIFFERS && try_to_match_wobbly_typedefs(node_lhs, node_rhs, *database)) {
|
||||
result.type = CompareResultType::MATCHES_FAVOUR_LHS;
|
||||
} else if(result.type == CompareResultType::DIFFERS && try_to_match_wobbly_typedefs(node_rhs, node_lhs, *database)) {
|
||||
result.type = CompareResultType::MATCHES_FAVOUR_RHS;
|
||||
}
|
||||
}
|
||||
|
||||
if(dest.type != result.type) {
|
||||
if(dest.type == CompareResultType::DIFFERS || result.type == CompareResultType::DIFFERS) {
|
||||
// If any of the inner types differ, the outer type does too.
|
||||
dest.type = CompareResultType::DIFFERS;
|
||||
} else if(dest.type == CompareResultType::MATCHES_CONFUSED || result.type == CompareResultType::MATCHES_CONFUSED) {
|
||||
// Propagate confusion.
|
||||
dest.type = CompareResultType::MATCHES_CONFUSED;
|
||||
} else if(dest.type == CompareResultType::MATCHES_FAVOUR_LHS && result.type == CompareResultType::MATCHES_FAVOUR_RHS) {
|
||||
// One of the results favours the LHS node and the other favours the
|
||||
// RHS node so we are confused.
|
||||
dest.type = CompareResultType::MATCHES_CONFUSED;
|
||||
} else if(dest.type == CompareResultType::MATCHES_FAVOUR_RHS && result.type == CompareResultType::MATCHES_FAVOUR_LHS) {
|
||||
// One of the results favours the LHS node and the other favours the
|
||||
// RHS node so we are confused.
|
||||
dest.type = CompareResultType::MATCHES_CONFUSED;
|
||||
} else if(dest.type == CompareResultType::MATCHES_FAVOUR_LHS || result.type == CompareResultType::MATCHES_FAVOUR_LHS) {
|
||||
// One of the results favours the LHS node and the other is neutral
|
||||
// so go with the LHS node.
|
||||
dest.type = CompareResultType::MATCHES_FAVOUR_LHS;
|
||||
} else if(dest.type == CompareResultType::MATCHES_FAVOUR_RHS || result.type == CompareResultType::MATCHES_FAVOUR_RHS) {
|
||||
// One of the results favours the RHS node and the other is neutral
|
||||
// so go with the RHS node.
|
||||
dest.type = CompareResultType::MATCHES_FAVOUR_RHS;
|
||||
}
|
||||
}
|
||||
|
||||
if(dest.fail_reason == CompareFailReason::NONE) {
|
||||
dest.fail_reason = result.fail_reason;
|
||||
}
|
||||
|
||||
return dest.type == CompareResultType::DIFFERS;
|
||||
}
|
||||
|
||||
static bool try_to_match_wobbly_typedefs(
|
||||
const Node& type_name_node, const Node& raw_node, const SymbolDatabase& database)
|
||||
{
|
||||
// Detect if one side has a typedef when the other just has the plain type.
|
||||
// This was previously a common reason why type deduplication would fail.
|
||||
if(type_name_node.descriptor != TYPE_NAME) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const TypeName& type_name = type_name_node.as<TypeName>();
|
||||
if(const TypeName::UnresolvedStabs* unresolved_stabs = type_name.unresolved_stabs.get()) {
|
||||
if(unresolved_stabs->referenced_file_handle == (u32) -1 || !unresolved_stabs->stabs_type_number.valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const SourceFile* source_file =
|
||||
database.source_files.symbol_from_handle(unresolved_stabs->referenced_file_handle);
|
||||
CCC_ASSERT(source_file);
|
||||
|
||||
auto handle = source_file->stabs_type_number_to_handle.find(unresolved_stabs->stabs_type_number);
|
||||
if(handle != source_file->stabs_type_number_to_handle.end()) {
|
||||
const DataType* referenced_type = database.data_types.symbol_from_handle(handle->second);
|
||||
CCC_ASSERT(referenced_type && referenced_type->type());
|
||||
// Don't compare 'intrusive' fields e.g. the offset.
|
||||
CompareResult new_result = compare_nodes(*referenced_type->type(), raw_node, &database, false);
|
||||
if(new_result.type != CompareResultType::DIFFERS) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* compare_fail_reason_to_string(CompareFailReason reason)
|
||||
{
|
||||
switch(reason) {
|
||||
case CompareFailReason::NONE: return "error";
|
||||
case CompareFailReason::DESCRIPTOR: return "descriptor";
|
||||
case CompareFailReason::STORAGE_CLASS: return "storage class";
|
||||
case CompareFailReason::NAME: return "name";
|
||||
case CompareFailReason::RELATIVE_OFFSET_BYTES: return "relative offset";
|
||||
case CompareFailReason::ABSOLUTE_OFFSET_BYTES: return "absolute offset";
|
||||
case CompareFailReason::BITFIELD_OFFSET_BITS: return "bitfield offset";
|
||||
case CompareFailReason::SIZE_BITS: return "size";
|
||||
case CompareFailReason::CONSTNESS: return "constness";
|
||||
case CompareFailReason::ARRAY_ELEMENT_COUNT: return "array element count";
|
||||
case CompareFailReason::BUILTIN_CLASS: return "builtin class";
|
||||
case CompareFailReason::FUNCTION_RETURN_TYPE_HAS_VALUE: return "function return type has value";
|
||||
case CompareFailReason::FUNCTION_PARAMAETER_COUNT: return "function paramaeter count";
|
||||
case CompareFailReason::FUNCTION_PARAMETERS_HAS_VALUE: return "function parameter";
|
||||
case CompareFailReason::FUNCTION_MODIFIER: return "function modifier";
|
||||
case CompareFailReason::ENUM_CONSTANTS: return "enum constant";
|
||||
case CompareFailReason::BASE_CLASS_COUNT: return "base class count";
|
||||
case CompareFailReason::FIELDS_SIZE: return "fields size";
|
||||
case CompareFailReason::MEMBER_FUNCTION_COUNT: return "member function count";
|
||||
case CompareFailReason::VTABLE_GLOBAL: return "vtable global";
|
||||
case CompareFailReason::TYPE_NAME: return "type name";
|
||||
case CompareFailReason::VARIABLE_CLASS: return "variable class";
|
||||
case CompareFailReason::VARIABLE_TYPE: return "variable type";
|
||||
case CompareFailReason::VARIABLE_STORAGE: return "variable storage";
|
||||
case CompareFailReason::VARIABLE_BLOCK: return "variable block";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char* node_type_to_string(const Node& node)
|
||||
{
|
||||
switch(node.descriptor) {
|
||||
case ARRAY: return "array";
|
||||
case BITFIELD: return "bitfield";
|
||||
case BUILTIN: return "builtin";
|
||||
case ENUM: return "enum";
|
||||
case ERROR_NODE: return "error";
|
||||
case FUNCTION: return "function";
|
||||
case POINTER_OR_REFERENCE: {
|
||||
const PointerOrReference& pointer_or_reference = node.as<PointerOrReference>();
|
||||
if(pointer_or_reference.is_pointer) {
|
||||
return "pointer";
|
||||
} else {
|
||||
return "reference";
|
||||
}
|
||||
}
|
||||
case POINTER_TO_DATA_MEMBER: return "pointer_to_data_member";
|
||||
case STRUCT_OR_UNION: {
|
||||
const StructOrUnion& struct_or_union = node.as<StructOrUnion>();
|
||||
if(struct_or_union.is_struct) {
|
||||
return "struct";
|
||||
} else {
|
||||
return "union";
|
||||
}
|
||||
}
|
||||
case TYPE_NAME: return "type_name";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char* storage_class_to_string(StorageClass storage_class)
|
||||
{
|
||||
switch(storage_class) {
|
||||
case STORAGE_CLASS_NONE: return "none";
|
||||
case STORAGE_CLASS_TYPEDEF: return "typedef";
|
||||
case STORAGE_CLASS_EXTERN: return "extern";
|
||||
case STORAGE_CLASS_STATIC: return "static";
|
||||
case STORAGE_CLASS_AUTO: return "auto";
|
||||
case STORAGE_CLASS_REGISTER: return "register";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char* access_specifier_to_string(AccessSpecifier specifier)
|
||||
{
|
||||
switch(specifier) {
|
||||
case AS_PUBLIC: return "public";
|
||||
case AS_PROTECTED: return "protected";
|
||||
case AS_PRIVATE: return "private";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char* builtin_class_to_string(BuiltInClass bclass)
|
||||
{
|
||||
switch(bclass) {
|
||||
case BuiltInClass::VOID_TYPE: return "void";
|
||||
case BuiltInClass::UNSIGNED_8: return "8-bit unsigned integer";
|
||||
case BuiltInClass::SIGNED_8: return "8-bit signed integer";
|
||||
case BuiltInClass::UNQUALIFIED_8: return "8-bit integer";
|
||||
case BuiltInClass::BOOL_8: return "8-bit boolean";
|
||||
case BuiltInClass::UNSIGNED_16: return "16-bit unsigned integer";
|
||||
case BuiltInClass::SIGNED_16: return "16-bit signed integer";
|
||||
case BuiltInClass::UNSIGNED_32: return "32-bit unsigned integer";
|
||||
case BuiltInClass::SIGNED_32: return "32-bit signed integer";
|
||||
case BuiltInClass::FLOAT_32: return "32-bit floating point";
|
||||
case BuiltInClass::UNSIGNED_64: return "64-bit unsigned integer";
|
||||
case BuiltInClass::SIGNED_64: return "64-bit signed integer";
|
||||
case BuiltInClass::FLOAT_64: return "64-bit floating point";
|
||||
case BuiltInClass::UNSIGNED_128: return "128-bit unsigned integer";
|
||||
case BuiltInClass::SIGNED_128: return "128-bit signed integer";
|
||||
case BuiltInClass::UNQUALIFIED_128: return "128-bit integer";
|
||||
case BuiltInClass::FLOAT_128: return "128-bit floating point";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
s32 builtin_class_size(BuiltInClass bclass)
|
||||
{
|
||||
switch(bclass) {
|
||||
case BuiltInClass::VOID_TYPE: return 0;
|
||||
case BuiltInClass::UNSIGNED_8: return 1;
|
||||
case BuiltInClass::SIGNED_8: return 1;
|
||||
case BuiltInClass::UNQUALIFIED_8: return 1;
|
||||
case BuiltInClass::BOOL_8: return 1;
|
||||
case BuiltInClass::UNSIGNED_16: return 2;
|
||||
case BuiltInClass::SIGNED_16: return 2;
|
||||
case BuiltInClass::UNSIGNED_32: return 4;
|
||||
case BuiltInClass::SIGNED_32: return 4;
|
||||
case BuiltInClass::FLOAT_32: return 4;
|
||||
case BuiltInClass::UNSIGNED_64: return 8;
|
||||
case BuiltInClass::SIGNED_64: return 8;
|
||||
case BuiltInClass::FLOAT_64: return 8;
|
||||
case BuiltInClass::UNSIGNED_128: return 16;
|
||||
case BuiltInClass::SIGNED_128: return 16;
|
||||
case BuiltInClass::UNQUALIFIED_128: return 16;
|
||||
case BuiltInClass::FLOAT_128: return 16;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
377
3rdparty/ccc/src/ccc/ast.h
vendored
Normal file
377
3rdparty/ccc/src/ccc/ast.h
vendored
Normal file
@@ -0,0 +1,377 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "symbol_database.h"
|
||||
|
||||
namespace ccc::ast {
|
||||
|
||||
enum NodeDescriptor : u8 {
|
||||
ARRAY,
|
||||
BITFIELD,
|
||||
BUILTIN,
|
||||
ENUM,
|
||||
ERROR_NODE,
|
||||
FUNCTION,
|
||||
POINTER_OR_REFERENCE,
|
||||
POINTER_TO_DATA_MEMBER,
|
||||
STRUCT_OR_UNION,
|
||||
TYPE_NAME
|
||||
};
|
||||
|
||||
enum AccessSpecifier {
|
||||
AS_PUBLIC = 0,
|
||||
AS_PROTECTED = 1,
|
||||
AS_PRIVATE = 2
|
||||
};
|
||||
|
||||
// To add a new type of node:
|
||||
// 1. Add it to the NodeDescriptor enum.
|
||||
// 2. Create a struct for it.
|
||||
// 3. Add support for it in for_each_node.
|
||||
// 4. Add support for it in compute_size_bytes_recursive.
|
||||
// 5. Add support for it in compare_nodes.
|
||||
// 6. Add support for it in node_type_to_string.
|
||||
// 7. Add support for it in CppPrinter::ast_node.
|
||||
// 8. Add support for it in write_json.
|
||||
// 9. Add support for it in refine_node.
|
||||
struct Node {
|
||||
const NodeDescriptor descriptor;
|
||||
u8 is_const : 1 = false;
|
||||
u8 is_volatile : 1 = false;
|
||||
u8 is_virtual_base_class : 1 = false;
|
||||
u8 is_vtable_pointer : 1 = false;
|
||||
u8 is_constructor_or_destructor : 1 = false;
|
||||
u8 is_special_member_function : 1 = false;
|
||||
u8 is_operator_member_function : 1 = false;
|
||||
u8 cannot_compute_size : 1 = false;
|
||||
u8 storage_class : 4 = STORAGE_CLASS_NONE;
|
||||
u8 access_specifier : 2 = AS_PUBLIC;
|
||||
|
||||
s32 size_bytes = -1;
|
||||
|
||||
// If the name isn't populated for a given node, the name from the last
|
||||
// ancestor to have one should be used i.e. when processing the tree you
|
||||
// should pass the name down.
|
||||
std::string name;
|
||||
|
||||
s32 offset_bytes = -1; // Offset relative to start of last inline struct/union.
|
||||
s32 size_bits = -1; // Size stored in the .mdebug symbol table, may not be set.
|
||||
|
||||
Node(NodeDescriptor d) : descriptor(d) {}
|
||||
Node(const Node& rhs) = default;
|
||||
virtual ~Node() {}
|
||||
|
||||
template <typename SubType>
|
||||
SubType& as() {
|
||||
CCC_ASSERT(descriptor == SubType::DESCRIPTOR);
|
||||
return *static_cast<SubType*>(this);
|
||||
}
|
||||
|
||||
template <typename SubType>
|
||||
const SubType& as() const {
|
||||
CCC_ASSERT(descriptor == SubType::DESCRIPTOR);
|
||||
return *static_cast<const SubType*>(this);
|
||||
}
|
||||
|
||||
template <typename SubType>
|
||||
static std::pair<const SubType&, const SubType&> as(const Node& lhs, const Node& rhs) {
|
||||
CCC_ASSERT(lhs.descriptor == SubType::DESCRIPTOR && rhs.descriptor == SubType::DESCRIPTOR);
|
||||
return std::pair<const SubType&, const SubType&>(static_cast<const SubType&>(lhs), static_cast<const SubType&>(rhs));
|
||||
}
|
||||
|
||||
void set_access_specifier(AccessSpecifier specifier, u32 importer_flags);
|
||||
|
||||
// If this node is a type name, repeatedly resolve it to the type it's
|
||||
// referencing, otherwise return (this, nullptr).
|
||||
std::pair<Node*, DataType*> physical_type(SymbolDatabase& database, s32 max_depth = 100);
|
||||
std::pair<const Node*, const DataType*> physical_type(const SymbolDatabase& database, s32 max_depth = 100) const;
|
||||
};
|
||||
|
||||
struct Array : Node {
|
||||
std::unique_ptr<Node> element_type;
|
||||
s32 element_count = -1;
|
||||
|
||||
Array() : Node(DESCRIPTOR) {}
|
||||
static const constexpr NodeDescriptor DESCRIPTOR = ARRAY;
|
||||
};
|
||||
|
||||
struct BitField : Node {
|
||||
s32 bitfield_offset_bits = -1; // Offset relative to the last byte (not the position of the underlying type!).
|
||||
std::unique_ptr<Node> underlying_type;
|
||||
|
||||
BitField() : Node(DESCRIPTOR) {}
|
||||
static const constexpr NodeDescriptor DESCRIPTOR = BITFIELD;
|
||||
};
|
||||
|
||||
enum class BuiltInClass {
|
||||
VOID_TYPE,
|
||||
UNSIGNED_8, SIGNED_8, UNQUALIFIED_8, BOOL_8,
|
||||
UNSIGNED_16, SIGNED_16,
|
||||
UNSIGNED_32, SIGNED_32, FLOAT_32,
|
||||
UNSIGNED_64, SIGNED_64, FLOAT_64,
|
||||
UNSIGNED_128, SIGNED_128, UNQUALIFIED_128, FLOAT_128
|
||||
};
|
||||
|
||||
struct BuiltIn : Node {
|
||||
BuiltInClass bclass = BuiltInClass::VOID_TYPE;
|
||||
|
||||
BuiltIn() : Node(DESCRIPTOR) {}
|
||||
static const constexpr NodeDescriptor DESCRIPTOR = BUILTIN;
|
||||
};
|
||||
|
||||
struct Enum : Node {
|
||||
std::vector<std::pair<s32, std::string>> constants;
|
||||
|
||||
Enum() : Node(DESCRIPTOR) {}
|
||||
static const constexpr NodeDescriptor DESCRIPTOR = ENUM;
|
||||
};
|
||||
|
||||
struct Error : Node {
|
||||
std::string message;
|
||||
|
||||
Error() : Node(ERROR_NODE) {}
|
||||
static const constexpr NodeDescriptor DESCRIPTOR = ERROR_NODE;
|
||||
};
|
||||
|
||||
enum class MemberFunctionModifier {
|
||||
NONE,
|
||||
STATIC,
|
||||
VIRTUAL
|
||||
};
|
||||
|
||||
const char* member_function_modifier_to_string(MemberFunctionModifier modifier);
|
||||
|
||||
struct Function : Node {
|
||||
std::optional<std::unique_ptr<Node>> return_type;
|
||||
std::optional<std::vector<std::unique_ptr<Node>>> parameters;
|
||||
MemberFunctionModifier modifier = MemberFunctionModifier::NONE;
|
||||
s32 vtable_index = -1;
|
||||
FunctionHandle definition_handle; // Filled in by fill_in_pointers_to_member_function_definitions.
|
||||
|
||||
Function() : Node(DESCRIPTOR) {}
|
||||
static const constexpr NodeDescriptor DESCRIPTOR = FUNCTION;
|
||||
};
|
||||
|
||||
struct PointerOrReference : Node {
|
||||
bool is_pointer = true;
|
||||
std::unique_ptr<Node> value_type;
|
||||
|
||||
PointerOrReference() : Node(DESCRIPTOR) {}
|
||||
static const constexpr NodeDescriptor DESCRIPTOR = POINTER_OR_REFERENCE;
|
||||
};
|
||||
|
||||
struct PointerToDataMember : Node {
|
||||
std::unique_ptr<Node> class_type;
|
||||
std::unique_ptr<Node> member_type;
|
||||
|
||||
PointerToDataMember() : Node(DESCRIPTOR) {}
|
||||
static const constexpr NodeDescriptor DESCRIPTOR = POINTER_TO_DATA_MEMBER;
|
||||
};
|
||||
|
||||
struct StructOrUnion : Node {
|
||||
bool is_struct = true;
|
||||
std::vector<std::unique_ptr<Node>> base_classes;
|
||||
std::vector<std::unique_ptr<Node>> fields;
|
||||
std::vector<std::unique_ptr<Node>> member_functions;
|
||||
|
||||
StructOrUnion() : Node(DESCRIPTOR) {}
|
||||
static const constexpr NodeDescriptor DESCRIPTOR = STRUCT_OR_UNION;
|
||||
|
||||
struct FlatField {
|
||||
// The field itself.
|
||||
const Node* node;
|
||||
// The symbol that owns the node.
|
||||
const DataType* symbol;
|
||||
// Offset of the innermost enclosing base class in the object.
|
||||
s32 base_offset = 0;
|
||||
};
|
||||
|
||||
// Generate a flat list of all the fields in this class as well as all the
|
||||
// base classes recursively, but only until the max_fields or max_depth
|
||||
// limits are reached. Return true if all the fields were enumerated.
|
||||
bool flatten_fields(
|
||||
std::vector<FlatField>& output,
|
||||
const DataType* symbol,
|
||||
const SymbolDatabase& database,
|
||||
bool skip_statics,
|
||||
s32 base_offset = 0,
|
||||
s32 max_fields = 100000,
|
||||
s32 max_depth = 100) const;
|
||||
};
|
||||
|
||||
enum class TypeNameSource : u8 {
|
||||
REFERENCE, // A STABS type reference.
|
||||
CROSS_REFERENCE, // A STABS cross reference.
|
||||
UNNAMED_THIS // A this parameter (or return type) referencing an unnamed type.
|
||||
};
|
||||
|
||||
const char* type_name_source_to_string(TypeNameSource source);
|
||||
|
||||
enum class ForwardDeclaredType {
|
||||
STRUCT,
|
||||
UNION,
|
||||
ENUM // Should be illegal but STABS supports cross references to enums so it's here.
|
||||
};
|
||||
|
||||
const char* forward_declared_type_to_string(ForwardDeclaredType type);
|
||||
|
||||
struct TypeName : Node {
|
||||
DataTypeHandle data_type_handle;
|
||||
TypeNameSource source = TypeNameSource::REFERENCE;
|
||||
bool is_forward_declared = false;
|
||||
|
||||
DataTypeHandle data_type_handle_unless_forward_declared() const;
|
||||
|
||||
struct UnresolvedStabs {
|
||||
std::string type_name;
|
||||
SourceFileHandle referenced_file_handle;
|
||||
StabsTypeNumber stabs_type_number;
|
||||
std::optional<ForwardDeclaredType> type;
|
||||
};
|
||||
|
||||
std::unique_ptr<UnresolvedStabs> unresolved_stabs;
|
||||
|
||||
TypeName() : Node(DESCRIPTOR) {}
|
||||
static const constexpr NodeDescriptor DESCRIPTOR = TYPE_NAME;
|
||||
};
|
||||
|
||||
enum class CompareResultType {
|
||||
MATCHES_NO_SWAP, // Both lhs and rhs are identical.
|
||||
MATCHES_CONFUSED, // Both lhs and rhs are almost identical, and we don't which is better.
|
||||
MATCHES_FAVOUR_LHS, // Both lhs and rhs are almost identical, but lhs is better.
|
||||
MATCHES_FAVOUR_RHS, // Both lhs and rhs are almost identical, but rhs is better.
|
||||
DIFFERS, // The two nodes differ substantially.
|
||||
};
|
||||
|
||||
enum class CompareFailReason {
|
||||
NONE,
|
||||
DESCRIPTOR,
|
||||
STORAGE_CLASS,
|
||||
NAME,
|
||||
RELATIVE_OFFSET_BYTES,
|
||||
ABSOLUTE_OFFSET_BYTES,
|
||||
BITFIELD_OFFSET_BITS,
|
||||
SIZE_BITS,
|
||||
CONSTNESS,
|
||||
ARRAY_ELEMENT_COUNT,
|
||||
BUILTIN_CLASS,
|
||||
FUNCTION_RETURN_TYPE_HAS_VALUE,
|
||||
FUNCTION_PARAMAETER_COUNT,
|
||||
FUNCTION_PARAMETERS_HAS_VALUE,
|
||||
FUNCTION_MODIFIER,
|
||||
ENUM_CONSTANTS,
|
||||
BASE_CLASS_COUNT,
|
||||
FIELDS_SIZE,
|
||||
MEMBER_FUNCTION_COUNT,
|
||||
VTABLE_GLOBAL,
|
||||
TYPE_NAME,
|
||||
VARIABLE_CLASS,
|
||||
VARIABLE_TYPE,
|
||||
VARIABLE_STORAGE,
|
||||
VARIABLE_BLOCK
|
||||
};
|
||||
|
||||
struct CompareResult {
|
||||
CompareResult(CompareResultType type) : type(type), fail_reason(CompareFailReason::NONE) {}
|
||||
CompareResult(CompareFailReason reason) : type(CompareResultType::DIFFERS), fail_reason(reason) {}
|
||||
CompareResultType type;
|
||||
CompareFailReason fail_reason;
|
||||
};
|
||||
|
||||
// Compare two AST nodes and their children recursively. This will only check
|
||||
// fields that will be equal for two versions of the same type from different
|
||||
// translation units.
|
||||
CompareResult compare_nodes(const Node& lhs, const Node& rhs, const SymbolDatabase* database, bool check_intrusive_fields);
|
||||
|
||||
const char* compare_fail_reason_to_string(CompareFailReason reason);
|
||||
const char* node_type_to_string(const Node& node);
|
||||
const char* storage_class_to_string(StorageClass storage_class);
|
||||
const char* access_specifier_to_string(AccessSpecifier specifier);
|
||||
const char* builtin_class_to_string(BuiltInClass bclass);
|
||||
|
||||
s32 builtin_class_size(BuiltInClass bclass);
|
||||
|
||||
enum TraversalOrder {
|
||||
PREORDER_TRAVERSAL,
|
||||
POSTORDER_TRAVERSAL
|
||||
};
|
||||
|
||||
enum ExplorationMode {
|
||||
EXPLORE_CHILDREN,
|
||||
DONT_EXPLORE_CHILDREN
|
||||
};
|
||||
|
||||
template <typename ThisNode, typename Callback>
|
||||
void for_each_node(ThisNode& node, TraversalOrder order, Callback callback)
|
||||
{
|
||||
if(order == PREORDER_TRAVERSAL && callback(node) == DONT_EXPLORE_CHILDREN) {
|
||||
return;
|
||||
}
|
||||
switch(node.descriptor) {
|
||||
case ARRAY: {
|
||||
auto& array = node.template as<Array>();
|
||||
for_each_node(*array.element_type.get(), order, callback);
|
||||
break;
|
||||
}
|
||||
case BITFIELD: {
|
||||
auto& bitfield = node.template as<BitField>();
|
||||
for_each_node(*bitfield.underlying_type.get(), order, callback);
|
||||
break;
|
||||
}
|
||||
case BUILTIN: {
|
||||
break;
|
||||
}
|
||||
case ENUM: {
|
||||
break;
|
||||
}
|
||||
case ERROR_NODE: {
|
||||
break;
|
||||
}
|
||||
case FUNCTION: {
|
||||
auto& func = node.template as<Function>();
|
||||
if(func.return_type.has_value()) {
|
||||
for_each_node(*func.return_type->get(), order, callback);
|
||||
}
|
||||
if(func.parameters.has_value()) {
|
||||
for(auto& child : *func.parameters) {
|
||||
for_each_node(*child.get(), order, callback);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case POINTER_OR_REFERENCE: {
|
||||
auto& pointer_or_reference = node.template as<PointerOrReference>();
|
||||
for_each_node(*pointer_or_reference.value_type.get(), order, callback);
|
||||
break;
|
||||
}
|
||||
case POINTER_TO_DATA_MEMBER: {
|
||||
auto& pointer = node.template as<PointerToDataMember>();
|
||||
for_each_node(*pointer.class_type.get(), order, callback);
|
||||
for_each_node(*pointer.member_type.get(), order, callback);
|
||||
break;
|
||||
}
|
||||
case STRUCT_OR_UNION: {
|
||||
auto& struct_or_union = node.template as<StructOrUnion>();
|
||||
for(auto& child : struct_or_union.base_classes) {
|
||||
for_each_node(*child.get(), order, callback);
|
||||
}
|
||||
for(auto& child : struct_or_union.fields) {
|
||||
for_each_node(*child.get(), order, callback);
|
||||
}
|
||||
for(auto& child : struct_or_union.member_functions) {
|
||||
for_each_node(*child.get(), order, callback);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TYPE_NAME: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(order == POSTORDER_TRAVERSAL) {
|
||||
callback(node);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
128
3rdparty/ccc/src/ccc/elf.cpp
vendored
Normal file
128
3rdparty/ccc/src/ccc/elf.cpp
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "elf.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
Result<ElfFile> ElfFile::parse(std::vector<u8> image)
|
||||
{
|
||||
ElfFile elf;
|
||||
elf.image = std::move(image);
|
||||
|
||||
const ElfIdentHeader* ident = get_unaligned<ElfIdentHeader>(elf.image, 0);
|
||||
CCC_CHECK(ident, "ELF ident header out of range.");
|
||||
CCC_CHECK(ident->magic == CCC_FOURCC("\x7f\x45\x4c\x46"), "Not an ELF file.");
|
||||
CCC_CHECK(ident->e_class == ElfIdentClass::B32, "Wrong ELF class (not 32 bit).");
|
||||
|
||||
const ElfFileHeader* header = get_unaligned<ElfFileHeader>(elf.image, sizeof(ElfIdentHeader));
|
||||
CCC_CHECK(header, "ELF file header out of range.");
|
||||
elf.file_header = *header;
|
||||
|
||||
const ElfSectionHeader* shstr_section_header =
|
||||
get_unaligned<ElfSectionHeader>(elf.image, header->shoff + header->shstrndx * sizeof(ElfSectionHeader));
|
||||
CCC_CHECK(shstr_section_header, "ELF section name header out of range.");
|
||||
|
||||
for(u32 i = 0; i < header->shnum; i++) {
|
||||
u64 header_offset = header->shoff + i * sizeof(ElfSectionHeader);
|
||||
const ElfSectionHeader* section_header = get_unaligned<ElfSectionHeader>(elf.image, header_offset);
|
||||
CCC_CHECK(section_header, "ELF section header out of range.");
|
||||
|
||||
std::optional<std::string_view> name = get_string(elf.image, shstr_section_header->offset + section_header->name);
|
||||
CCC_CHECK(name.has_value(), "ELF section name out of range.");
|
||||
|
||||
ElfSection& section = elf.sections.emplace_back();
|
||||
section.name = *name;
|
||||
section.header = *section_header;
|
||||
}
|
||||
|
||||
for(u32 i = 0; i < header->phnum; i++) {
|
||||
u64 header_offset = header->phoff + i * sizeof(ElfProgramHeader);
|
||||
const ElfProgramHeader* program_header = get_unaligned<ElfProgramHeader>(elf.image, header_offset);
|
||||
CCC_CHECK(program_header, "ELF program header out of range.");
|
||||
|
||||
elf.segments.emplace_back(*program_header);
|
||||
}
|
||||
|
||||
return elf;
|
||||
}
|
||||
|
||||
Result<void> ElfFile::create_section_symbols(
|
||||
SymbolDatabase& database, const SymbolGroup& group) const
|
||||
{
|
||||
for(const ElfSection& section : sections) {
|
||||
Address address = Address::non_zero(section.header.addr);
|
||||
|
||||
Result<Section*> symbol = database.sections.create_symbol(
|
||||
section.name, address, group.source, group.module_symbol);
|
||||
CCC_RETURN_IF_ERROR(symbol);
|
||||
|
||||
(*symbol)->set_size(section.header.size);
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
const ElfSection* ElfFile::lookup_section(const char* name) const
|
||||
{
|
||||
for(const ElfSection& section : sections) {
|
||||
if(section.name == name) {
|
||||
return §ion;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::optional<u32> ElfFile::file_offset_to_virtual_address(u32 file_offset) const
|
||||
{
|
||||
for(const ElfProgramHeader& segment : segments) {
|
||||
if(file_offset >= segment.offset && file_offset < segment.offset + segment.filesz) {
|
||||
return segment.vaddr + file_offset - segment.offset;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const ElfProgramHeader* ElfFile::entry_point_segment() const
|
||||
{
|
||||
const ccc::ElfProgramHeader* entry_segment = nullptr;
|
||||
for(const ccc::ElfProgramHeader& segment : segments) {
|
||||
if(file_header.entry >= segment.vaddr && file_header.entry < segment.vaddr + segment.filesz) {
|
||||
entry_segment = &segment;
|
||||
}
|
||||
}
|
||||
return entry_segment;
|
||||
}
|
||||
|
||||
std::optional<std::span<const u8>> ElfFile::get_virtual(u32 address, u32 size) const
|
||||
{
|
||||
u32 end_address = address + size;
|
||||
|
||||
if(end_address >= address) {
|
||||
for(const ElfProgramHeader& segment : segments) {
|
||||
if(address >= segment.vaddr && end_address <= segment.vaddr + segment.filesz) {
|
||||
size_t begin_offset = segment.offset + (address - segment.vaddr);
|
||||
size_t end_offset = begin_offset + size;
|
||||
if(begin_offset <= image.size() && end_offset <= image.size()) {
|
||||
return std::span<const u8>(image.data() + begin_offset, image.data() + end_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool ElfFile::copy_virtual(u8* dest, u32 address, u32 size) const
|
||||
{
|
||||
std::optional<std::span<const u8>> block = get_virtual(address, size);
|
||||
if(!block.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(dest, block->data(), size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
160
3rdparty/ccc/src/ccc/elf.h
vendored
Normal file
160
3rdparty/ccc/src/ccc/elf.h
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "symbol_database.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
enum class ElfIdentClass : u8 {
|
||||
B32 = 0x1,
|
||||
B64 = 0x2
|
||||
};
|
||||
|
||||
CCC_PACKED_STRUCT(ElfIdentHeader,
|
||||
/* 0x0 */ u32 magic; // 7f 45 4c 46
|
||||
/* 0x4 */ ElfIdentClass e_class;
|
||||
/* 0x5 */ u8 endianess;
|
||||
/* 0x6 */ u8 version;
|
||||
/* 0x7 */ u8 os_abi;
|
||||
/* 0x8 */ u8 abi_version;
|
||||
/* 0x9 */ u8 pad[7];
|
||||
)
|
||||
|
||||
enum class ElfFileType : u16 {
|
||||
NONE = 0x00,
|
||||
REL = 0x01,
|
||||
EXEC = 0x02,
|
||||
DYN = 0x03,
|
||||
CORE = 0x04,
|
||||
LOOS = 0xfe00,
|
||||
HIOS = 0xfeff,
|
||||
LOPROC = 0xff00,
|
||||
HIPROC = 0xffff
|
||||
};
|
||||
|
||||
enum class ElfMachine : u16 {
|
||||
MIPS = 0x08
|
||||
};
|
||||
|
||||
CCC_PACKED_STRUCT(ElfFileHeader,
|
||||
/* 0x10 */ ElfFileType type;
|
||||
/* 0x12 */ ElfMachine machine;
|
||||
/* 0x14 */ u32 version;
|
||||
/* 0x18 */ u32 entry;
|
||||
/* 0x1c */ u32 phoff;
|
||||
/* 0x20 */ u32 shoff;
|
||||
/* 0x24 */ u32 flags;
|
||||
/* 0x28 */ u16 ehsize;
|
||||
/* 0x2a */ u16 phentsize;
|
||||
/* 0x2c */ u16 phnum;
|
||||
/* 0x2e */ u16 shentsize;
|
||||
/* 0x30 */ u16 shnum;
|
||||
/* 0x32 */ u16 shstrndx;
|
||||
)
|
||||
|
||||
enum class ElfSectionType : u32 {
|
||||
NULL_SECTION = 0x0,
|
||||
PROGBITS = 0x1,
|
||||
SYMTAB = 0x2,
|
||||
STRTAB = 0x3,
|
||||
RELA = 0x4,
|
||||
HASH = 0x5,
|
||||
DYNAMIC = 0x6,
|
||||
NOTE = 0x7,
|
||||
NOBITS = 0x8,
|
||||
REL = 0x9,
|
||||
SHLIB = 0xa,
|
||||
DYNSYM = 0xb,
|
||||
INIT_ARRAY = 0xe,
|
||||
FINI_ARRAY = 0xf,
|
||||
PREINIT_ARRAY = 0x10,
|
||||
GROUP = 0x11,
|
||||
SYMTAB_SHNDX = 0x12,
|
||||
NUM = 0x13,
|
||||
LOOS = 0x60000000,
|
||||
MIPS_DEBUG = 0x70000005
|
||||
};
|
||||
|
||||
CCC_PACKED_STRUCT(ElfSectionHeader,
|
||||
/* 0x00 */ u32 name;
|
||||
/* 0x04 */ ElfSectionType type;
|
||||
/* 0x08 */ u32 flags;
|
||||
/* 0x0c */ u32 addr;
|
||||
/* 0x10 */ u32 offset;
|
||||
/* 0x14 */ u32 size;
|
||||
/* 0x18 */ u32 link;
|
||||
/* 0x1c */ u32 info;
|
||||
/* 0x20 */ u32 addralign;
|
||||
/* 0x24 */ u32 entsize;
|
||||
)
|
||||
|
||||
struct ElfSection {
|
||||
std::string name;
|
||||
ElfSectionHeader header;
|
||||
};
|
||||
|
||||
CCC_PACKED_STRUCT(ElfProgramHeader,
|
||||
/* 0x00 */ u32 type;
|
||||
/* 0x04 */ u32 offset;
|
||||
/* 0x08 */ u32 vaddr;
|
||||
/* 0x0c */ u32 paddr;
|
||||
/* 0x10 */ u32 filesz;
|
||||
/* 0x14 */ u32 memsz;
|
||||
/* 0x18 */ u32 flags;
|
||||
/* 0x1c */ u32 align;
|
||||
)
|
||||
|
||||
struct ElfFile {
|
||||
ElfFileHeader file_header;
|
||||
std::vector<u8> image;
|
||||
std::vector<ElfSection> sections;
|
||||
std::vector<ElfProgramHeader> segments;
|
||||
|
||||
// Parse the ELF file header, section headers and program headers.
|
||||
static Result<ElfFile> parse(std::vector<u8> image);
|
||||
|
||||
// Create a section object for each section header in the ELF file.
|
||||
Result<void> create_section_symbols(SymbolDatabase& database, const SymbolGroup& group) const;
|
||||
|
||||
const ElfSection* lookup_section(const char* name) const;
|
||||
std::optional<u32> file_offset_to_virtual_address(u32 file_offset) const;
|
||||
|
||||
// Find the program header for the segment that contains the entry point.
|
||||
const ElfProgramHeader* entry_point_segment() const;
|
||||
|
||||
// Retrieve a block of data in an ELF file given its address and size.
|
||||
std::optional<std::span<const u8>> get_virtual(u32 address, u32 size) const;
|
||||
|
||||
// Copy a block of data in an ELF file to the destination buffer given its
|
||||
// address and size.
|
||||
bool copy_virtual(u8* dest, u32 address, u32 size) const;
|
||||
|
||||
// Retrieve an object of type T from an ELF file given its address.
|
||||
template <typename T>
|
||||
std::optional<T> get_object_virtual(u32 address) const
|
||||
{
|
||||
std::optional<std::span<const u8>> result = get_virtual(address, sizeof(T));
|
||||
if(!result.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return *(T*) result->data();
|
||||
}
|
||||
|
||||
// Retrieve an array of objects of type T from an ELF file given its
|
||||
// address and element count.
|
||||
template <typename T>
|
||||
std::optional<std::span<const T>> get_array_virtual(u32 address, u32 element_count) const
|
||||
{
|
||||
std::optional<std::span<const u8>> result = get_virtual(address, element_count * sizeof(T));
|
||||
if(!result.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return std::span<const T>((T*) result->data(), (T*) (result->data() + result->size()));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
214
3rdparty/ccc/src/ccc/elf_symtab.cpp
vendored
Normal file
214
3rdparty/ccc/src/ccc/elf_symtab.cpp
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "elf_symtab.h"
|
||||
|
||||
#include "importer_flags.h"
|
||||
|
||||
namespace ccc::elf {
|
||||
|
||||
enum class SymbolBind : u8 {
|
||||
LOCAL = 0,
|
||||
GLOBAL = 1,
|
||||
WEAK = 2,
|
||||
NUM = 3,
|
||||
GNU_UNIQUE = 10
|
||||
};
|
||||
|
||||
enum class SymbolType : u8 {
|
||||
NOTYPE = 0,
|
||||
OBJECT = 1,
|
||||
FUNC = 2,
|
||||
SECTION = 3,
|
||||
FILE = 4,
|
||||
COMMON = 5,
|
||||
TLS = 6,
|
||||
NUM = 7,
|
||||
GNU_IFUNC = 10
|
||||
};
|
||||
|
||||
enum class SymbolVisibility {
|
||||
DEFAULT = 0,
|
||||
INTERNAL = 1,
|
||||
HIDDEN = 2,
|
||||
PROTECTED = 3
|
||||
};
|
||||
|
||||
CCC_PACKED_STRUCT(Symbol,
|
||||
/* 0x0 */ u32 name;
|
||||
/* 0x4 */ u32 value;
|
||||
/* 0x8 */ u32 size;
|
||||
/* 0xc */ u8 info;
|
||||
/* 0xd */ u8 other;
|
||||
/* 0xe */ u16 shndx;
|
||||
|
||||
SymbolType type() const { return (SymbolType) (info & 0xf); }
|
||||
SymbolBind bind() const { return (SymbolBind) (info >> 4); }
|
||||
SymbolVisibility visibility() const { return (SymbolVisibility) (other & 0x3); }
|
||||
)
|
||||
|
||||
static const char* symbol_bind_to_string(SymbolBind bind);
|
||||
static const char* symbol_type_to_string(SymbolType type);
|
||||
static const char* symbol_visibility_to_string(SymbolVisibility visibility);
|
||||
|
||||
Result<void> import_symbols(
|
||||
SymbolDatabase& database,
|
||||
const SymbolGroup& group,
|
||||
std::span<const u8> symtab,
|
||||
std::span<const u8> strtab,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler)
|
||||
{
|
||||
for(u32 i = 0; i < symtab.size() / sizeof(Symbol); i++) {
|
||||
const Symbol* symbol = get_unaligned<Symbol>(symtab, i * sizeof(Symbol));
|
||||
CCC_ASSERT(symbol);
|
||||
|
||||
Address address;
|
||||
if(symbol->value != 0) {
|
||||
address = symbol->value;
|
||||
}
|
||||
|
||||
if(!address.valid() || symbol->visibility() != SymbolVisibility::DEFAULT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!(importer_flags & DONT_DEDUPLICATE_SYMBOLS)) {
|
||||
if(database.functions.first_handle_from_starting_address(address).valid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(database.global_variables.first_handle_from_starting_address(address).valid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(database.local_variables.first_handle_from_starting_address(address).valid()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::string_view> string_view = get_string(strtab, symbol->name);
|
||||
CCC_CHECK(string_view.has_value(), "Symbol string out of range.");
|
||||
std::string string(*string_view);
|
||||
|
||||
switch(symbol->type()) {
|
||||
case SymbolType::NOTYPE: {
|
||||
Result<Label*> label = database.labels.create_symbol(
|
||||
std::move(string), group.source, group.module_symbol, address, importer_flags, demangler);
|
||||
CCC_RETURN_IF_ERROR(label);
|
||||
|
||||
// These symbols get emitted at the same addresses as functions
|
||||
// and aren't extremely useful, so we want to mark them to
|
||||
// prevent them from possibly being used as function names.
|
||||
(*label)->is_junk =
|
||||
(*label)->name() == "__gnu_compiled_c" ||
|
||||
(*label)->name() == "__gnu_compiled_cplusplus" ||
|
||||
(*label)->name() == "gcc2_compiled.";
|
||||
|
||||
break;
|
||||
}
|
||||
case SymbolType::OBJECT: {
|
||||
if(symbol->size != 0) {
|
||||
Result<GlobalVariable*> global_variable = database.global_variables.create_symbol(
|
||||
std::move(string), group.source, group.module_symbol, address, importer_flags, demangler);
|
||||
CCC_RETURN_IF_ERROR(global_variable);
|
||||
|
||||
if(*global_variable) {
|
||||
(*global_variable)->set_size(symbol->size);
|
||||
}
|
||||
} else {
|
||||
Result<Label*> label = database.labels.create_symbol(
|
||||
std::move(string), group.source, group.module_symbol, address, importer_flags, demangler);
|
||||
CCC_RETURN_IF_ERROR(label);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SymbolType::FUNC: {
|
||||
Result<Function*> function = database.functions.create_symbol(
|
||||
std::move(string), group.source, group.module_symbol, address, importer_flags, demangler);
|
||||
CCC_RETURN_IF_ERROR(function);
|
||||
|
||||
if(*function) {
|
||||
(*function)->set_size(symbol->size);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SymbolType::FILE: {
|
||||
Result<SourceFile*> source_file = database.source_files.create_symbol(
|
||||
std::move(string), group.source, group.module_symbol);
|
||||
CCC_RETURN_IF_ERROR(source_file);
|
||||
|
||||
break;
|
||||
}
|
||||
default: {}
|
||||
}
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> print_symbol_table(FILE* out, std::span<const u8> symtab, std::span<const u8> strtab)
|
||||
{
|
||||
fprintf(out, "ELF SYMBOLS:\n");
|
||||
fprintf(out, " Num: Value Size Type Bind Vis Ndx Name\n");
|
||||
|
||||
for(u32 i = 0; i < symtab.size() / sizeof(Symbol); i++) {
|
||||
const Symbol* symbol = get_unaligned<Symbol>(symtab, i * sizeof(Symbol));
|
||||
CCC_ASSERT(symbol);
|
||||
|
||||
const char* type = symbol_type_to_string(symbol->type());
|
||||
const char* bind = symbol_bind_to_string(symbol->bind());
|
||||
const char* visibility = symbol_visibility_to_string(symbol->visibility());
|
||||
|
||||
std::optional<std::string_view> string = get_string(strtab, symbol->name);
|
||||
CCC_CHECK(string.has_value(), "Symbol string out of range.");
|
||||
|
||||
fprintf(out, "%6u: %08x %5u %-7s %-7s %-7s %3u %s\n",
|
||||
i, symbol->value, symbol->size, type, bind, visibility, symbol->shndx, string->data());
|
||||
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
static const char* symbol_bind_to_string(SymbolBind bind)
|
||||
{
|
||||
switch(bind) {
|
||||
case SymbolBind::LOCAL: return "LOCAL";
|
||||
case SymbolBind::GLOBAL: return "GLOBAL";
|
||||
case SymbolBind::WEAK: return "WEAK";
|
||||
case SymbolBind::NUM: return "NUM";
|
||||
case SymbolBind::GNU_UNIQUE: return "GNU_UNIQUE";
|
||||
}
|
||||
return "ERROR";
|
||||
}
|
||||
|
||||
static const char* symbol_type_to_string(SymbolType type)
|
||||
{
|
||||
switch(type) {
|
||||
case SymbolType::NOTYPE: return "NOTYPE";
|
||||
case SymbolType::OBJECT: return "OBJECT";
|
||||
case SymbolType::FUNC: return "FUNC";
|
||||
case SymbolType::SECTION: return "SECTION";
|
||||
case SymbolType::FILE: return "FILE";
|
||||
case SymbolType::COMMON: return "COMMON";
|
||||
case SymbolType::TLS: return "TLS";
|
||||
case SymbolType::NUM: return "NUM";
|
||||
case SymbolType::GNU_IFUNC: return "GNU_IFUNC";
|
||||
}
|
||||
return "ERROR";
|
||||
}
|
||||
|
||||
static const char* symbol_visibility_to_string(SymbolVisibility visibility)
|
||||
{
|
||||
switch(visibility) {
|
||||
case SymbolVisibility::DEFAULT: return "DEFAULT";
|
||||
case SymbolVisibility::INTERNAL: return "INTERNAL";
|
||||
case SymbolVisibility::HIDDEN: return "HIDDEN";
|
||||
case SymbolVisibility::PROTECTED: return "PROTECTED";
|
||||
}
|
||||
return "ERROR";
|
||||
}
|
||||
|
||||
}
|
||||
20
3rdparty/ccc/src/ccc/elf_symtab.h
vendored
Normal file
20
3rdparty/ccc/src/ccc/elf_symtab.h
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "symbol_database.h"
|
||||
|
||||
namespace ccc::elf {
|
||||
|
||||
Result<void> import_symbols(
|
||||
SymbolDatabase& database,
|
||||
const SymbolGroup& group,
|
||||
std::span<const u8> symtab,
|
||||
std::span<const u8> strtab,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler);
|
||||
|
||||
Result<void> print_symbol_table(FILE* out, std::span<const u8> symtab, std::span<const u8> strtab);
|
||||
|
||||
}
|
||||
95
3rdparty/ccc/src/ccc/importer_flags.cpp
vendored
Normal file
95
3rdparty/ccc/src/ccc/importer_flags.cpp
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "importer_flags.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
const std::vector<ImporterFlagInfo> IMPORTER_FLAGS = {
|
||||
{DEMANGLE_PARAMETERS, "--demangle-parameters", {
|
||||
"Include parameters in demangled function names."
|
||||
}},
|
||||
{DEMANGLE_RETURN_TYPE, "--demangle-return-type", {
|
||||
"Include return types at the end of demangled",
|
||||
"function names if they're available."
|
||||
}},
|
||||
{DONT_DEDUPLICATE_SYMBOLS, "--dont-deduplicate-symbols", {
|
||||
"Do not deduplicate matching symbols from",
|
||||
"different symbol tables. This options has no",
|
||||
"effect on data types."
|
||||
}},
|
||||
{DONT_DEDUPLICATE_TYPES, "--dont-deduplicate-types", {
|
||||
"Do not deduplicate data types from different",
|
||||
"translation units."
|
||||
}},
|
||||
{DONT_DEMANGLE_NAMES, "--dont-demangle-names", {
|
||||
"Do not demangle function names, global variable",
|
||||
"names, or overloaded operator names."
|
||||
}},
|
||||
{INCLUDE_GENERATED_MEMBER_FUNCTIONS, "--include-generated-functions", {
|
||||
"Output member functions that were likely",
|
||||
"automatically generated by the compiler."
|
||||
}},
|
||||
{NO_ACCESS_SPECIFIERS, "--no-access-specifiers", {
|
||||
"Do not print access specifiers."
|
||||
}},
|
||||
{NO_MEMBER_FUNCTIONS, "--no-member-functions", {
|
||||
"Do not print member functions."
|
||||
}},
|
||||
{NO_OPTIMIZED_OUT_FUNCTIONS, "--no-optimized-out-functions", {
|
||||
"Discard functions that were optimized out."
|
||||
}},
|
||||
{STRICT_PARSING, "--strict", {
|
||||
"Make more types of errors fatal."
|
||||
}},
|
||||
{TYPEDEF_ALL_ENUMS, "--typedef-all-enums", {
|
||||
"Force all emitted C++ enums to be defined using",
|
||||
"a typedef. With STABS, it is not always possible",
|
||||
"to determine if an enum was like this in the",
|
||||
"original source code, so this option should be",
|
||||
"useful for reverse engineering C projects."
|
||||
}},
|
||||
{TYPEDEF_ALL_STRUCTS, "--typedef-all-structs", {
|
||||
"Force all emitted C++ structure types to be",
|
||||
"defined using a typedef."
|
||||
}},
|
||||
{TYPEDEF_ALL_UNIONS, "--typedef-all-unions", {
|
||||
"Force all emitted C++ union types to be defined",
|
||||
"using a typedef."
|
||||
}},
|
||||
{UNIQUE_FUNCTIONS, "--unique-functions", {
|
||||
" If multiple identical .mdebug function symbols",
|
||||
"are present, find the one that seems to have",
|
||||
"actually been included in the linked binary, and",
|
||||
"remove the addresses from all the rest. Using",
|
||||
"this importer flag in combination with",
|
||||
"--no-optimized-out-functions will remove these",
|
||||
"duplicate function symbols entirely."
|
||||
}}
|
||||
};
|
||||
|
||||
u32 parse_importer_flag(const char* argument)
|
||||
{
|
||||
for(const ImporterFlagInfo& flag : IMPORTER_FLAGS) {
|
||||
if(strcmp(flag.argument, argument) == 0) {
|
||||
return flag.flag;
|
||||
}
|
||||
}
|
||||
return NO_IMPORTER_FLAGS;
|
||||
}
|
||||
|
||||
void print_importer_flags_help(FILE* out)
|
||||
{
|
||||
for(const ImporterFlagInfo& flag : IMPORTER_FLAGS) {
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, " %-29s ", flag.argument);
|
||||
for(size_t i = 0; i < flag.help_text.size(); i++) {
|
||||
if(i > 0) {
|
||||
fprintf(out, " ");
|
||||
}
|
||||
fprintf(out, "%s\n", flag.help_text[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
39
3rdparty/ccc/src/ccc/importer_flags.h
vendored
Normal file
39
3rdparty/ccc/src/ccc/importer_flags.h
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
enum ImporterFlags {
|
||||
NO_IMPORTER_FLAGS = 0,
|
||||
DEMANGLE_PARAMETERS = (1 << 0),
|
||||
DEMANGLE_RETURN_TYPE = (1 << 1),
|
||||
DONT_DEDUPLICATE_SYMBOLS = (1 << 2),
|
||||
DONT_DEDUPLICATE_TYPES = (1 << 3),
|
||||
DONT_DEMANGLE_NAMES = (1 << 4),
|
||||
INCLUDE_GENERATED_MEMBER_FUNCTIONS = (1 << 5),
|
||||
NO_ACCESS_SPECIFIERS = (1 << 6),
|
||||
NO_MEMBER_FUNCTIONS = (1 << 7),
|
||||
NO_OPTIMIZED_OUT_FUNCTIONS = (1 << 8),
|
||||
STRICT_PARSING = (1 << 9),
|
||||
TYPEDEF_ALL_ENUMS = (1 << 10),
|
||||
TYPEDEF_ALL_STRUCTS = (1 << 11),
|
||||
TYPEDEF_ALL_UNIONS = (1 << 12),
|
||||
UNIQUE_FUNCTIONS = (1 << 13)
|
||||
};
|
||||
|
||||
struct ImporterFlagInfo {
|
||||
ImporterFlags flag;
|
||||
const char* argument;
|
||||
std::vector<const char*> help_text;
|
||||
};
|
||||
|
||||
extern const std::vector<ImporterFlagInfo> IMPORTER_FLAGS;
|
||||
|
||||
u32 parse_importer_flag(const char* argument);
|
||||
void print_importer_flags_help(FILE* out);
|
||||
|
||||
}
|
||||
349
3rdparty/ccc/src/ccc/mdebug_analysis.cpp
vendored
Normal file
349
3rdparty/ccc/src/ccc/mdebug_analysis.cpp
vendored
Normal file
@@ -0,0 +1,349 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "mdebug_analysis.h"
|
||||
|
||||
#include "stabs_to_ast.h"
|
||||
|
||||
namespace ccc::mdebug {
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::stab_magic(const char* magic)
|
||||
{
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::source_file(const char* path, Address text_address)
|
||||
{
|
||||
if(m_next_relative_path.empty()) {
|
||||
m_next_relative_path = m_source_file.command_line_path;
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::data_type(const ParsedSymbol& symbol)
|
||||
{
|
||||
Result<std::unique_ptr<ast::Node>> node = stabs_type_to_ast(
|
||||
*symbol.name_colon_type.type.get(), nullptr, m_stabs_to_ast_state, 0, false, false);
|
||||
CCC_RETURN_IF_ERROR(node);
|
||||
|
||||
if(symbol.is_typedef && (*node)->descriptor == ast::STRUCT_OR_UNION) {
|
||||
ast::StructOrUnion& struct_or_union = (*node)->as<ast::StructOrUnion>();
|
||||
const std::string& name = symbol.name_colon_type.name;
|
||||
StabsTypeNumber type_number = symbol.name_colon_type.type->type_number;
|
||||
fix_recursively_emitted_structures(struct_or_union, name, type_number, m_stabs_to_ast_state.file_handle);
|
||||
}
|
||||
|
||||
bool is_struct = (*node)->descriptor == ast::STRUCT_OR_UNION && (*node)->as<ast::StructOrUnion>().is_struct;
|
||||
bool force_typedef =
|
||||
((m_context.importer_flags & TYPEDEF_ALL_ENUMS) && (*node)->descriptor == ast::ENUM) ||
|
||||
((m_context.importer_flags & TYPEDEF_ALL_STRUCTS) && (*node)->descriptor == ast::STRUCT_OR_UNION && is_struct) ||
|
||||
((m_context.importer_flags & TYPEDEF_ALL_UNIONS) && (*node)->descriptor == ast::STRUCT_OR_UNION && !is_struct);
|
||||
|
||||
(*node)->name = (symbol.name_colon_type.name == " ") ? "" : symbol.name_colon_type.name;
|
||||
if(symbol.is_typedef || force_typedef) {
|
||||
(*node)->storage_class = STORAGE_CLASS_TYPEDEF;
|
||||
}
|
||||
|
||||
const char* name = (*node)->name.c_str();
|
||||
StabsTypeNumber number = symbol.name_colon_type.type->type_number;
|
||||
|
||||
if(m_context.importer_flags & DONT_DEDUPLICATE_TYPES) {
|
||||
Result<DataType*> data_type = m_database.data_types.create_symbol(
|
||||
name, m_context.group.source, m_context.group.module_symbol);
|
||||
CCC_RETURN_IF_ERROR(data_type);
|
||||
|
||||
m_source_file.stabs_type_number_to_handle[number] = (*data_type)->handle();
|
||||
(*data_type)->set_type(std::move(*node));
|
||||
|
||||
(*data_type)->files = {m_source_file.handle()};
|
||||
} else {
|
||||
Result<ccc::DataType*> type = m_database.create_data_type_if_unique(
|
||||
std::move(*node), number, name, m_source_file, m_context.group);
|
||||
CCC_RETURN_IF_ERROR(type);
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::global_variable(
|
||||
const char* mangled_name, Address address, const StabsType& type, bool is_static, GlobalStorageLocation location)
|
||||
{
|
||||
Result<GlobalVariable*> global = m_database.global_variables.create_symbol(
|
||||
mangled_name, m_context.group.source, m_context.group.module_symbol, address, m_context.importer_flags, m_context.demangler);
|
||||
CCC_RETURN_IF_ERROR(global);
|
||||
CCC_ASSERT(*global);
|
||||
|
||||
m_global_variables.emplace_back((*global)->handle());
|
||||
|
||||
Result<std::unique_ptr<ast::Node>> node = stabs_type_to_ast(type, nullptr, m_stabs_to_ast_state, 0, true, false);
|
||||
CCC_RETURN_IF_ERROR(node);
|
||||
|
||||
if(is_static) {
|
||||
(*global)->storage_class = STORAGE_CLASS_STATIC;
|
||||
}
|
||||
(*global)->set_type(std::move(*node));
|
||||
|
||||
(*global)->storage.location = location;
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::sub_source_file(const char* path, Address text_address)
|
||||
{
|
||||
if(m_current_function && m_state == IN_FUNCTION_BEGINNING) {
|
||||
Function::SubSourceFile& sub = m_current_function->sub_source_files.emplace_back();
|
||||
sub.address = text_address;
|
||||
sub.relative_path = path;
|
||||
} else {
|
||||
m_next_relative_path = path;
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::procedure(
|
||||
const char* mangled_name, Address address, const ProcedureDescriptor* procedure_descriptor, bool is_static)
|
||||
{
|
||||
if(!m_current_function || strcmp(mangled_name, m_current_function->mangled_name().c_str()) != 0) {
|
||||
Result<void> result = create_function(mangled_name, address);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
}
|
||||
|
||||
if(is_static) {
|
||||
m_current_function->storage_class = STORAGE_CLASS_STATIC;
|
||||
}
|
||||
|
||||
if(procedure_descriptor) {
|
||||
m_current_function->stack_frame_size = procedure_descriptor->frame_size;
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::label(const char* label, Address address, s32 line_number)
|
||||
{
|
||||
if(address.valid() && m_current_function && label[0] == '$') {
|
||||
Function::LineNumberPair& pair = m_current_function->line_numbers.emplace_back();
|
||||
pair.address = address;
|
||||
pair.line_number = line_number;
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::text_end(const char* name, s32 function_size)
|
||||
{
|
||||
if(m_state == IN_FUNCTION_BEGINNING) {
|
||||
CCC_CHECK(m_current_function, "END TEXT symbol outside of function.");
|
||||
m_current_function->set_size(function_size);
|
||||
m_state = IN_FUNCTION_END;
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::function(const char* mangled_name, const StabsType& return_type, Address address)
|
||||
{
|
||||
if(!m_current_function || strcmp(mangled_name, m_current_function->mangled_name().c_str()) != 0) {
|
||||
Result<void> result = create_function(mangled_name, address);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
} else {
|
||||
// For MTV Music Maker 2, the addresses for static functions stored in
|
||||
// the PROC symbols are relative to the translation unit, while the
|
||||
// addresses stored in the FUN symbol are absolute. This is the only
|
||||
// game I've found that seems to have this problem, but since in all
|
||||
// other cases it seems all these addresses are all absolute, I may as
|
||||
// well add in a hack here to deal with it.
|
||||
bool no_module_base_address = m_context.group.module_symbol && m_context.group.module_symbol->address().get_or_zero() == 0;
|
||||
bool new_address_greater = address.valid() && address > m_current_function->address();
|
||||
if(no_module_base_address && new_address_greater) {
|
||||
m_database.functions.move_symbol(m_current_function->handle(), address);
|
||||
}
|
||||
}
|
||||
|
||||
Result<std::unique_ptr<ast::Node>> node = stabs_type_to_ast(return_type, nullptr, m_stabs_to_ast_state, 0, true, true);
|
||||
CCC_RETURN_IF_ERROR(node);
|
||||
m_current_function->set_type(std::move(*node));
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::function_end()
|
||||
{
|
||||
if(m_current_function) {
|
||||
m_current_function->set_parameter_variables(std::move(m_current_parameter_variables), m_database);
|
||||
m_current_function->set_local_variables(std::move(m_current_local_variables), m_database);
|
||||
}
|
||||
|
||||
m_current_function = nullptr;
|
||||
m_current_parameter_variables = std::vector<ParameterVariableHandle>();
|
||||
m_current_local_variables = std::vector<LocalVariableHandle>();
|
||||
|
||||
m_blocks.clear();
|
||||
m_pending_local_variables.clear();
|
||||
|
||||
m_state = NOT_IN_FUNCTION;
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::parameter(
|
||||
const char* name, const StabsType& type, bool is_stack, s32 value, bool is_by_reference)
|
||||
{
|
||||
CCC_CHECK(m_current_function, "Parameter symbol before first func/proc symbol.");
|
||||
|
||||
Result<ParameterVariable*> parameter_variable = m_database.parameter_variables.create_symbol(
|
||||
name, m_context.group.source, m_context.group.module_symbol);
|
||||
CCC_RETURN_IF_ERROR(parameter_variable);
|
||||
|
||||
m_current_parameter_variables.emplace_back((*parameter_variable)->handle());
|
||||
|
||||
Result<std::unique_ptr<ast::Node>> node = stabs_type_to_ast(type, nullptr, m_stabs_to_ast_state, 0, true, true);
|
||||
CCC_RETURN_IF_ERROR(node);
|
||||
(*parameter_variable)->set_type(std::move(*node));
|
||||
|
||||
if(is_stack) {
|
||||
StackStorage& stack_storage = (*parameter_variable)->storage.emplace<StackStorage>();
|
||||
stack_storage.stack_pointer_offset = value;
|
||||
} else {
|
||||
RegisterStorage& register_storage = (*parameter_variable)->storage.emplace<RegisterStorage>();
|
||||
register_storage.dbx_register_number = value;
|
||||
register_storage.is_by_reference = is_by_reference;
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::local_variable(
|
||||
const char* name, const StabsType& type, u32 value, StabsSymbolDescriptor desc, SymbolClass sclass)
|
||||
{
|
||||
if(!m_current_function) {
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Address address = (desc == StabsSymbolDescriptor::STATIC_LOCAL_VARIABLE) ? value : Address();
|
||||
Result<LocalVariable*> local_variable = m_database.local_variables.create_symbol(
|
||||
name, address, m_context.group.source, m_context.group.module_symbol);
|
||||
CCC_RETURN_IF_ERROR(local_variable);
|
||||
|
||||
m_current_local_variables.emplace_back((*local_variable)->handle());
|
||||
m_pending_local_variables.emplace_back((*local_variable)->handle());
|
||||
|
||||
Result<std::unique_ptr<ast::Node>> node = stabs_type_to_ast(type, nullptr, m_stabs_to_ast_state, 0, true, false);
|
||||
CCC_RETURN_IF_ERROR(node);
|
||||
|
||||
if(desc == StabsSymbolDescriptor::STATIC_LOCAL_VARIABLE) {
|
||||
GlobalStorage& global_storage = (*local_variable)->storage.emplace<GlobalStorage>();
|
||||
std::optional<GlobalStorageLocation> location_opt =
|
||||
symbol_class_to_global_variable_location(sclass);
|
||||
CCC_CHECK(location_opt.has_value(),
|
||||
"Invalid static local variable location %s.",
|
||||
symbol_class(sclass));
|
||||
global_storage.location = *location_opt;
|
||||
(*node)->storage_class = STORAGE_CLASS_STATIC;
|
||||
} else if(desc == StabsSymbolDescriptor::REGISTER_VARIABLE) {
|
||||
RegisterStorage& register_storage = (*local_variable)->storage.emplace<RegisterStorage>();
|
||||
register_storage.dbx_register_number = (s32) value;
|
||||
} else if(desc == StabsSymbolDescriptor::LOCAL_VARIABLE) {
|
||||
StackStorage& stack_storage = (*local_variable)->storage.emplace<StackStorage>();
|
||||
stack_storage.stack_pointer_offset = (s32) value;
|
||||
} else {
|
||||
return CCC_FAILURE("LocalSymbolTableAnalyser::local_variable() called with bad symbol descriptor.");
|
||||
}
|
||||
|
||||
(*local_variable)->set_type(std::move(*node));
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::lbrac(s32 begin_offset)
|
||||
{
|
||||
for(LocalVariableHandle local_variable_handle : m_pending_local_variables) {
|
||||
if(LocalVariable* local_variable = m_database.local_variables.symbol_from_handle(local_variable_handle)) {
|
||||
local_variable->live_range.low = m_source_file.address().value + begin_offset;
|
||||
}
|
||||
}
|
||||
|
||||
m_blocks.emplace_back(std::move(m_pending_local_variables));
|
||||
m_pending_local_variables = {};
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::rbrac(s32 end_offset)
|
||||
{
|
||||
CCC_CHECK(!m_blocks.empty(), "RBRAC symbol without a matching LBRAC symbol.");
|
||||
|
||||
std::vector<LocalVariableHandle>& variables = m_blocks.back();
|
||||
for(LocalVariableHandle local_variable_handle : variables) {
|
||||
if(LocalVariable* local_variable = m_database.local_variables.symbol_from_handle(local_variable_handle)) {
|
||||
local_variable->live_range.high = m_source_file.address().value + end_offset;
|
||||
}
|
||||
}
|
||||
|
||||
m_blocks.pop_back();
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::finish()
|
||||
{
|
||||
CCC_CHECK(m_state != IN_FUNCTION_BEGINNING,
|
||||
"Unexpected end of symbol table for '%s'.", m_source_file.name().c_str());
|
||||
|
||||
if(m_current_function) {
|
||||
Result<void> result = function_end();
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
}
|
||||
|
||||
m_source_file.set_functions(std::move(m_functions), m_database);
|
||||
m_source_file.set_global_variables(std::move(m_global_variables), m_database);
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> LocalSymbolTableAnalyser::create_function(const char* mangled_name, Address address)
|
||||
{
|
||||
if(m_current_function) {
|
||||
Result<void> result = function_end();
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
}
|
||||
|
||||
Result<Function*> function = m_database.functions.create_symbol(
|
||||
mangled_name, m_context.group.source, m_context.group.module_symbol, address, m_context.importer_flags, m_context.demangler);
|
||||
CCC_RETURN_IF_ERROR(function);
|
||||
CCC_ASSERT(*function);
|
||||
m_current_function = *function;
|
||||
|
||||
m_functions.emplace_back(m_current_function->handle());
|
||||
|
||||
m_state = IN_FUNCTION_BEGINNING;
|
||||
|
||||
if(!m_next_relative_path.empty() && m_current_function->relative_path != m_source_file.command_line_path) {
|
||||
m_current_function->relative_path = m_next_relative_path;
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
std::optional<GlobalStorageLocation> symbol_class_to_global_variable_location(SymbolClass symbol_class)
|
||||
{
|
||||
std::optional<GlobalStorageLocation> location;
|
||||
switch(symbol_class) {
|
||||
case SymbolClass::NIL: location = GlobalStorageLocation::NIL; break;
|
||||
case SymbolClass::DATA: location = GlobalStorageLocation::DATA; break;
|
||||
case SymbolClass::BSS: location = GlobalStorageLocation::BSS; break;
|
||||
case SymbolClass::ABS: location = GlobalStorageLocation::ABS; break;
|
||||
case SymbolClass::SDATA: location = GlobalStorageLocation::SDATA; break;
|
||||
case SymbolClass::SBSS: location = GlobalStorageLocation::SBSS; break;
|
||||
case SymbolClass::RDATA: location = GlobalStorageLocation::RDATA; break;
|
||||
case SymbolClass::COMMON: location = GlobalStorageLocation::COMMON; break;
|
||||
case SymbolClass::SCOMMON: location = GlobalStorageLocation::SCOMMON; break;
|
||||
case SymbolClass::SUNDEFINED: location = GlobalStorageLocation::SUNDEFINED; break;
|
||||
default: {}
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
}
|
||||
99
3rdparty/ccc/src/ccc/mdebug_analysis.h
vendored
Normal file
99
3rdparty/ccc/src/ccc/mdebug_analysis.h
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "importer_flags.h"
|
||||
#include "mdebug_section.h"
|
||||
#include "mdebug_symbols.h"
|
||||
#include "stabs.h"
|
||||
#include "stabs_to_ast.h"
|
||||
#include "symbol_database.h"
|
||||
|
||||
namespace ccc::mdebug {
|
||||
|
||||
struct AnalysisContext {
|
||||
const mdebug::SymbolTableReader* reader = nullptr;
|
||||
const std::map<u32, const mdebug::Symbol*>* external_functions = nullptr;
|
||||
const std::map<std::string, const mdebug::Symbol*>* external_globals = nullptr;
|
||||
SymbolGroup group;
|
||||
u32 importer_flags = NO_IMPORTER_FLAGS;
|
||||
DemanglerFunctions demangler;
|
||||
};
|
||||
|
||||
class LocalSymbolTableAnalyser {
|
||||
public:
|
||||
LocalSymbolTableAnalyser(SymbolDatabase& database, const StabsToAstState& stabs_to_ast_state, const AnalysisContext& context, SourceFile& source_file)
|
||||
: m_database(database)
|
||||
, m_context(context)
|
||||
, m_stabs_to_ast_state(stabs_to_ast_state)
|
||||
, m_source_file(source_file) {}
|
||||
|
||||
// Functions for processing individual symbols.
|
||||
//
|
||||
// In most cases these symbols will appear in the following order:
|
||||
// PROC TEXT
|
||||
// ... line numbers ... ($LM<N>)
|
||||
// END TEXT
|
||||
// LABEL TEXT FUN
|
||||
// ... parameters ...
|
||||
// ... blocks ... (... local variables ... LBRAC ... subblocks ... RBRAC)
|
||||
// NIL NIL FUN
|
||||
//
|
||||
// For some compiler versions the symbols can appear in this order:
|
||||
// LABEL TEXT FUN
|
||||
// ... parameters ...
|
||||
// first line number ($LM1)
|
||||
// PROC TEXT
|
||||
// ... line numbers ... ($LM<N>)
|
||||
// END TEXT
|
||||
// ... blocks ... (... local variables ... LBRAC ... subblocks ... RBRAC)
|
||||
Result<void> stab_magic(const char* magic);
|
||||
Result<void> source_file(const char* path, Address text_address);
|
||||
Result<void> data_type(const ParsedSymbol& symbol);
|
||||
Result<void> global_variable(
|
||||
const char* mangled_name, Address address, const StabsType& type, bool is_static, GlobalStorageLocation location);
|
||||
Result<void> sub_source_file(const char* name, Address text_address);
|
||||
Result<void> procedure(
|
||||
const char* mangled_name, Address address, const ProcedureDescriptor* procedure_descriptor, bool is_static);
|
||||
Result<void> label(const char* label, Address address, s32 line_number);
|
||||
Result<void> text_end(const char* name, s32 function_size);
|
||||
Result<void> function(const char* mangled_name, const StabsType& return_type, Address address);
|
||||
Result<void> function_end();
|
||||
Result<void> parameter(
|
||||
const char* name, const StabsType& type, bool is_stack, s32 value, bool is_by_reference);
|
||||
Result<void> local_variable(
|
||||
const char* name, const StabsType& type, u32 value, StabsSymbolDescriptor desc, SymbolClass sclass);
|
||||
Result<void> lbrac(s32 begin_offset);
|
||||
Result<void> rbrac(s32 end_offset);
|
||||
|
||||
Result<void> finish();
|
||||
|
||||
Result<void> create_function(const char* mangled_name, Address address);
|
||||
|
||||
protected:
|
||||
enum AnalysisState {
|
||||
NOT_IN_FUNCTION,
|
||||
IN_FUNCTION_BEGINNING,
|
||||
IN_FUNCTION_END
|
||||
};
|
||||
|
||||
SymbolDatabase& m_database;
|
||||
const AnalysisContext& m_context;
|
||||
const StabsToAstState& m_stabs_to_ast_state;
|
||||
|
||||
AnalysisState m_state = NOT_IN_FUNCTION;
|
||||
SourceFile& m_source_file;
|
||||
std::vector<FunctionHandle> m_functions;
|
||||
std::vector<GlobalVariableHandle> m_global_variables;
|
||||
Function* m_current_function = nullptr;
|
||||
std::vector<ParameterVariableHandle> m_current_parameter_variables;
|
||||
std::vector<LocalVariableHandle> m_current_local_variables;
|
||||
std::vector<std::vector<LocalVariableHandle>> m_blocks;
|
||||
std::vector<LocalVariableHandle> m_pending_local_variables;
|
||||
std::string m_next_relative_path;
|
||||
};
|
||||
|
||||
std::optional<GlobalStorageLocation> symbol_class_to_global_variable_location(SymbolClass symbol_class);
|
||||
|
||||
};
|
||||
668
3rdparty/ccc/src/ccc/mdebug_importer.cpp
vendored
Normal file
668
3rdparty/ccc/src/ccc/mdebug_importer.cpp
vendored
Normal file
@@ -0,0 +1,668 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "mdebug_importer.h"
|
||||
|
||||
namespace ccc::mdebug {
|
||||
|
||||
static Result<void> resolve_type_names(
|
||||
SymbolDatabase& database, const SymbolGroup& group, u32 importer_flags);
|
||||
static Result<void> resolve_type_name(
|
||||
ast::TypeName& type_name,
|
||||
SymbolDatabase& database,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags);
|
||||
static void compute_size_bytes(ast::Node& node, SymbolDatabase& database);
|
||||
static void detect_duplicate_functions(SymbolDatabase& database, const SymbolGroup& group);
|
||||
static void detect_fake_functions(SymbolDatabase& database, const std::map<u32, const mdebug::Symbol*>& external_functions, const SymbolGroup& group);
|
||||
static void destroy_optimized_out_functions(
|
||||
SymbolDatabase& database, const SymbolGroup& group);
|
||||
|
||||
Result<void> import_symbol_table(
|
||||
SymbolDatabase& database,
|
||||
std::span<const u8> elf,
|
||||
s32 section_offset,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags,
|
||||
const DemanglerFunctions& demangler,
|
||||
const std::atomic_bool* interrupt)
|
||||
{
|
||||
SymbolTableReader reader;
|
||||
|
||||
Result<void> reader_result = reader.init(elf, section_offset);
|
||||
CCC_RETURN_IF_ERROR(reader_result);
|
||||
|
||||
Result<std::vector<mdebug::Symbol>> external_symbols = reader.parse_external_symbols();
|
||||
CCC_RETURN_IF_ERROR(external_symbols);
|
||||
|
||||
// The addresses of the global variables aren't present in the local symbol
|
||||
// table, so here we extract them from the external table. In addition, for
|
||||
// some games we need to cross reference the function symbols in the local
|
||||
// symbol table with the entries in the external symbol table.
|
||||
std::map<u32, const mdebug::Symbol*> external_functions;
|
||||
std::map<std::string, const mdebug::Symbol*> external_globals;
|
||||
for(const mdebug::Symbol& external : *external_symbols) {
|
||||
if(external.symbol_type == mdebug::SymbolType::PROC) {
|
||||
external_functions[external.value] = &external;
|
||||
}
|
||||
|
||||
if(external.symbol_type == mdebug::SymbolType::GLOBAL
|
||||
&& (external.symbol_class != mdebug::SymbolClass::UNDEFINED)) {
|
||||
external_globals[external.string] = &external;
|
||||
}
|
||||
}
|
||||
|
||||
// Bundle together some unchanging state to pass to import_files.
|
||||
AnalysisContext context;
|
||||
context.reader = &reader;
|
||||
context.external_functions = &external_functions;
|
||||
context.external_globals = &external_globals;
|
||||
context.group = group;
|
||||
context.importer_flags = importer_flags;
|
||||
context.demangler = demangler;
|
||||
|
||||
Result<void> result = import_files(database, context, interrupt);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> import_files(SymbolDatabase& database, const AnalysisContext& context, const std::atomic_bool* interrupt)
|
||||
{
|
||||
Result<s32> file_count = context.reader->file_count();
|
||||
CCC_RETURN_IF_ERROR(file_count);
|
||||
|
||||
for(s32 i = 0; i < *file_count; i++) {
|
||||
if(interrupt && *interrupt) {
|
||||
return CCC_FAILURE("Operation interrupted by user.");
|
||||
}
|
||||
|
||||
Result<mdebug::File> file = context.reader->parse_file(i);
|
||||
CCC_RETURN_IF_ERROR(file);
|
||||
|
||||
Result<void> result = import_file(database, *file, context);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
}
|
||||
|
||||
// The files field may be modified by further analysis passes, so we
|
||||
// need to save this information here.
|
||||
for(DataType& data_type : database.data_types) {
|
||||
if(context.group.is_in_group(data_type) && data_type.files.size() == 1) {
|
||||
data_type.only_defined_in_single_translation_unit = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Lookup data types and store data type handles in type names.
|
||||
Result<void> type_name_result = resolve_type_names(database, context.group, context.importer_flags);
|
||||
CCC_RETURN_IF_ERROR(type_name_result);
|
||||
|
||||
// Compute the size in bytes of all the AST nodes.
|
||||
database.for_each_symbol([&](ccc::Symbol& symbol) {
|
||||
if(context.group.is_in_group(symbol) && symbol.type()) {
|
||||
compute_size_bytes(*symbol.type(), database);
|
||||
}
|
||||
});
|
||||
|
||||
// Propagate the size information to the global variable symbols.
|
||||
for(GlobalVariable& global_variable : database.global_variables) {
|
||||
if(global_variable.type() && global_variable.type()->size_bytes > -1) {
|
||||
global_variable.set_size((u32) global_variable.type()->size_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Propagate the size information to the static local variable symbols.
|
||||
for(LocalVariable& local_variable : database.local_variables) {
|
||||
bool is_static_local = std::holds_alternative<GlobalStorage>(local_variable.storage);
|
||||
if(is_static_local && local_variable.type() && local_variable.type()->size_bytes > -1) {
|
||||
local_variable.set_size((u32) local_variable.type()->size_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Some games (e.g. Jet X2O) have multiple function symbols across different
|
||||
// translation units with the same name and address.
|
||||
if(context.importer_flags & UNIQUE_FUNCTIONS) {
|
||||
detect_duplicate_functions(database, context.group);
|
||||
}
|
||||
|
||||
// If multiple functions appear at the same address, discard the addresses
|
||||
// of all of them except the real one.
|
||||
if(context.external_functions) {
|
||||
detect_fake_functions(database, *context.external_functions, context.group);
|
||||
}
|
||||
|
||||
// Remove functions with no address. If there are any such functions, this
|
||||
// will invalidate all pointers to symbols.
|
||||
if(context.importer_flags & NO_OPTIMIZED_OUT_FUNCTIONS) {
|
||||
destroy_optimized_out_functions(database, context.group);
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> import_file(SymbolDatabase& database, const mdebug::File& input, const AnalysisContext& context)
|
||||
{
|
||||
// Parse the stab strings into a data structure that's vaguely
|
||||
// one-to-one with the text-based representation.
|
||||
u32 importer_flags_for_this_file = context.importer_flags;
|
||||
Result<std::vector<ParsedSymbol>> symbols = parse_symbols(input.symbols, importer_flags_for_this_file);
|
||||
CCC_RETURN_IF_ERROR(symbols);
|
||||
|
||||
// In stabs, types can be referenced by their number from other stabs,
|
||||
// so here we build a map of type numbers to the parsed types.
|
||||
std::map<StabsTypeNumber, const StabsType*> stabs_types;
|
||||
for(const ParsedSymbol& symbol : *symbols) {
|
||||
if(symbol.type == ParsedSymbolType::NAME_COLON_TYPE) {
|
||||
symbol.name_colon_type.type->enumerate_numbered_types(stabs_types);
|
||||
}
|
||||
}
|
||||
|
||||
Result<SourceFile*> source_file = database.source_files.create_symbol(
|
||||
input.full_path, input.address, context.group.source, context.group.module_symbol);
|
||||
CCC_RETURN_IF_ERROR(source_file);
|
||||
|
||||
(*source_file)->working_dir = input.working_dir;
|
||||
(*source_file)->command_line_path = input.command_line_path;
|
||||
|
||||
// Sometimes the INFO symbols contain information about what toolchain
|
||||
// version was used for building the executable.
|
||||
for(const mdebug::Symbol& symbol : input.symbols) {
|
||||
if(symbol.symbol_class == mdebug::SymbolClass::INFO && strcmp(symbol.string, "@stabs") != 0) {
|
||||
(*source_file)->toolchain_version_info.emplace(symbol.string);
|
||||
}
|
||||
}
|
||||
|
||||
StabsToAstState stabs_to_ast_state;
|
||||
stabs_to_ast_state.file_handle = (*source_file)->handle().value;
|
||||
stabs_to_ast_state.stabs_types = &stabs_types;
|
||||
stabs_to_ast_state.importer_flags = importer_flags_for_this_file;
|
||||
stabs_to_ast_state.demangler = context.demangler;
|
||||
|
||||
// Convert the parsed stabs symbols to a more standard C AST.
|
||||
LocalSymbolTableAnalyser analyser(database, stabs_to_ast_state, context, **source_file);
|
||||
for(const ParsedSymbol& symbol : *symbols) {
|
||||
if(symbol.duplicate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(symbol.type) {
|
||||
case ParsedSymbolType::NAME_COLON_TYPE: {
|
||||
switch(symbol.name_colon_type.descriptor) {
|
||||
case StabsSymbolDescriptor::LOCAL_FUNCTION:
|
||||
case StabsSymbolDescriptor::GLOBAL_FUNCTION: {
|
||||
const char* name = symbol.name_colon_type.name.c_str();
|
||||
const StabsType& type = *symbol.name_colon_type.type.get();
|
||||
Result<void> result = analyser.function(name, type, symbol.raw->value);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
break;
|
||||
}
|
||||
case StabsSymbolDescriptor::REFERENCE_PARAMETER_A:
|
||||
case StabsSymbolDescriptor::REGISTER_PARAMETER:
|
||||
case StabsSymbolDescriptor::VALUE_PARAMETER:
|
||||
case StabsSymbolDescriptor::REFERENCE_PARAMETER_V: {
|
||||
const char* name = symbol.name_colon_type.name.c_str();
|
||||
const StabsType& type = *symbol.name_colon_type.type.get();
|
||||
bool is_stack_variable = symbol.name_colon_type.descriptor == StabsSymbolDescriptor::VALUE_PARAMETER;
|
||||
bool is_by_reference = symbol.name_colon_type.descriptor == StabsSymbolDescriptor::REFERENCE_PARAMETER_A
|
||||
|| symbol.name_colon_type.descriptor == StabsSymbolDescriptor::REFERENCE_PARAMETER_V;
|
||||
|
||||
Result<void> result = analyser.parameter(name, type, is_stack_variable, symbol.raw->value, is_by_reference);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
break;
|
||||
}
|
||||
case StabsSymbolDescriptor::REGISTER_VARIABLE:
|
||||
case StabsSymbolDescriptor::LOCAL_VARIABLE:
|
||||
case StabsSymbolDescriptor::STATIC_LOCAL_VARIABLE: {
|
||||
const char* name = symbol.name_colon_type.name.c_str();
|
||||
const StabsType& type = *symbol.name_colon_type.type.get();
|
||||
Result<void> result = analyser.local_variable(
|
||||
name, type, symbol.raw->value, symbol.name_colon_type.descriptor, symbol.raw->symbol_class);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
break;
|
||||
}
|
||||
case StabsSymbolDescriptor::GLOBAL_VARIABLE:
|
||||
case StabsSymbolDescriptor::STATIC_GLOBAL_VARIABLE: {
|
||||
const char* name = symbol.name_colon_type.name.c_str();
|
||||
u32 address = -1;
|
||||
std::optional<GlobalStorageLocation> location =
|
||||
symbol_class_to_global_variable_location(symbol.raw->symbol_class);
|
||||
if(symbol.name_colon_type.descriptor == StabsSymbolDescriptor::GLOBAL_VARIABLE) {
|
||||
// The address for non-static global variables is
|
||||
// only stored in the external symbol table (and
|
||||
// the ELF symbol table), so we pull that
|
||||
// information in here.
|
||||
if(context.external_globals) {
|
||||
auto global_symbol = context.external_globals->find(symbol.name_colon_type.name);
|
||||
if(global_symbol != context.external_globals->end()) {
|
||||
address = (u32) global_symbol->second->value;
|
||||
location = symbol_class_to_global_variable_location(global_symbol->second->symbol_class);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// And for static global variables it's just stored
|
||||
// in the local symbol table.
|
||||
address = (u32) symbol.raw->value;
|
||||
}
|
||||
CCC_CHECK(location.has_value(), "Invalid global variable location.")
|
||||
const StabsType& type = *symbol.name_colon_type.type.get();
|
||||
bool is_static = symbol.name_colon_type.descriptor == StabsSymbolDescriptor::STATIC_GLOBAL_VARIABLE;
|
||||
Result<void> result = analyser.global_variable(name, address, type, is_static, *location);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
break;
|
||||
}
|
||||
case StabsSymbolDescriptor::TYPE_NAME:
|
||||
case StabsSymbolDescriptor::ENUM_STRUCT_OR_TYPE_TAG: {
|
||||
Result<void> result = analyser.data_type(symbol);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ParsedSymbolType::SOURCE_FILE: {
|
||||
Result<void> result = analyser.source_file(symbol.raw->string, symbol.raw->value);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
break;
|
||||
}
|
||||
case ParsedSymbolType::SUB_SOURCE_FILE: {
|
||||
Result<void> result = analyser.sub_source_file(symbol.raw->string, symbol.raw->value);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
break;
|
||||
}
|
||||
case ParsedSymbolType::LBRAC: {
|
||||
Result<void> result = analyser.lbrac(symbol.raw->value);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
break;
|
||||
}
|
||||
case ParsedSymbolType::RBRAC: {
|
||||
Result<void> result = analyser.rbrac(symbol.raw->value);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
break;
|
||||
}
|
||||
case ParsedSymbolType::FUNCTION_END: {
|
||||
Result<void> result = analyser.function_end();
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
break;
|
||||
}
|
||||
case ParsedSymbolType::NON_STABS: {
|
||||
if(symbol.raw->symbol_class == mdebug::SymbolClass::TEXT) {
|
||||
if(symbol.raw->symbol_type == mdebug::SymbolType::PROC) {
|
||||
Result<void> result = analyser.procedure(symbol.raw->string, symbol.raw->value, symbol.raw->procedure_descriptor, false);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
} else if(symbol.raw->symbol_type == mdebug::SymbolType::STATICPROC) {
|
||||
Result<void> result = analyser.procedure(symbol.raw->string, symbol.raw->value, symbol.raw->procedure_descriptor, true);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
} else if(symbol.raw->symbol_type == mdebug::SymbolType::LABEL) {
|
||||
Result<void> result = analyser.label(symbol.raw->string, symbol.raw->value, symbol.raw->index);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
} else if(symbol.raw->symbol_type == mdebug::SymbolType::END) {
|
||||
Result<void> result = analyser.text_end(symbol.raw->string, symbol.raw->value);
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Result<void> result = analyser.finish();
|
||||
CCC_RETURN_IF_ERROR(result);
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
static Result<void> resolve_type_names(
|
||||
SymbolDatabase& database, const SymbolGroup& group, u32 importer_flags)
|
||||
{
|
||||
Result<void> result;
|
||||
database.for_each_symbol([&](ccc::Symbol& symbol) {
|
||||
if(group.is_in_group(symbol) && symbol.type()) {
|
||||
ast::for_each_node(*symbol.type(), ast::PREORDER_TRAVERSAL, [&](ast::Node& node) {
|
||||
if(node.descriptor == ast::TYPE_NAME) {
|
||||
Result<void> type_name_result = resolve_type_name(node.as<ast::TypeName>(), database, group, importer_flags);
|
||||
if(!type_name_result.success()) {
|
||||
result = std::move(type_name_result);
|
||||
}
|
||||
}
|
||||
return ast::EXPLORE_CHILDREN;
|
||||
});
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
static Result<void> resolve_type_name(
|
||||
ast::TypeName& type_name,
|
||||
SymbolDatabase& database,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags)
|
||||
{
|
||||
ast::TypeName::UnresolvedStabs* unresolved_stabs = type_name.unresolved_stabs.get();
|
||||
if(!unresolved_stabs) {
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
// Lookup the type by its STABS type number. This path ensures that the
|
||||
// correct type is found even if multiple types have the same name.
|
||||
if(unresolved_stabs->referenced_file_handle != (u32) -1 && unresolved_stabs->stabs_type_number.valid()) {
|
||||
const SourceFile* source_file = database.source_files.symbol_from_handle(unresolved_stabs->referenced_file_handle);
|
||||
CCC_ASSERT(source_file);
|
||||
auto handle = source_file->stabs_type_number_to_handle.find(unresolved_stabs->stabs_type_number);
|
||||
if(handle != source_file->stabs_type_number_to_handle.end()) {
|
||||
type_name.data_type_handle = handle->second.value;
|
||||
type_name.is_forward_declared = false;
|
||||
type_name.unresolved_stabs.reset();
|
||||
return Result<void>();
|
||||
}
|
||||
}
|
||||
|
||||
// Looking up the type by its STABS type number failed, so look for it by
|
||||
// its name instead. This happens when a type is forward declared but not
|
||||
// defined in a given translation unit.
|
||||
if(!unresolved_stabs->type_name.empty()) {
|
||||
for(auto& name_handle : database.data_types.handles_from_name(unresolved_stabs->type_name)) {
|
||||
DataType* data_type = database.data_types.symbol_from_handle(name_handle.second);
|
||||
if(data_type && group.is_in_group(*data_type)) {
|
||||
type_name.data_type_handle = name_handle.second.value;
|
||||
type_name.is_forward_declared = true;
|
||||
type_name.unresolved_stabs.reset();
|
||||
return Result<void>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If this branch is taken it means the type name was probably from an
|
||||
// automatically generated member function of a nested struct trying to
|
||||
// reference the struct (for the this parameter). We shouldn't create a
|
||||
// forward declared type in this case.
|
||||
if(type_name.source == ast::TypeNameSource::UNNAMED_THIS) {
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
// Type lookup failed. This happens when a type is forward declared in a
|
||||
// translation unit with symbols but is not defined in one. We haven't
|
||||
// already created a forward declared type, so we create one now.
|
||||
std::unique_ptr<ast::Node> forward_declared_node;
|
||||
if(unresolved_stabs->type.has_value()) {
|
||||
switch(*unresolved_stabs->type) {
|
||||
case ast::ForwardDeclaredType::STRUCT: {
|
||||
std::unique_ptr<ast::StructOrUnion> node = std::make_unique<ast::StructOrUnion>();
|
||||
node->is_struct = true;
|
||||
forward_declared_node = std::move(node);
|
||||
break;
|
||||
}
|
||||
case ast::ForwardDeclaredType::UNION: {
|
||||
std::unique_ptr<ast::StructOrUnion> node = std::make_unique<ast::StructOrUnion>();
|
||||
node->is_struct = false;
|
||||
forward_declared_node = std::move(node);
|
||||
break;
|
||||
}
|
||||
case ast::ForwardDeclaredType::ENUM: {
|
||||
std::unique_ptr<ast::Enum> node = std::make_unique<ast::Enum>();
|
||||
forward_declared_node = std::move(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(forward_declared_node) {
|
||||
Result<DataType*> forward_declared_type = database.data_types.create_symbol(
|
||||
unresolved_stabs->type_name, group.source, group.module_symbol);
|
||||
CCC_RETURN_IF_ERROR(forward_declared_type);
|
||||
|
||||
(*forward_declared_type)->set_type(std::move(forward_declared_node));
|
||||
(*forward_declared_type)->not_defined_in_any_translation_unit = true;
|
||||
|
||||
type_name.data_type_handle = (*forward_declared_type)->handle().value;
|
||||
type_name.is_forward_declared = true;
|
||||
type_name.unresolved_stabs.reset();
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
const char* error_message = "Unresolved %s type name '%s' with STABS type number (%d,%d).";
|
||||
if(importer_flags & STRICT_PARSING) {
|
||||
return CCC_FAILURE(error_message,
|
||||
ast::type_name_source_to_string(type_name.source),
|
||||
type_name.unresolved_stabs->type_name.c_str(),
|
||||
type_name.unresolved_stabs->stabs_type_number.file,
|
||||
type_name.unresolved_stabs->stabs_type_number.type);
|
||||
} else {
|
||||
CCC_WARN(error_message,
|
||||
ast::type_name_source_to_string(type_name.source),
|
||||
type_name.unresolved_stabs->type_name.c_str(),
|
||||
type_name.unresolved_stabs->stabs_type_number.file,
|
||||
type_name.unresolved_stabs->stabs_type_number.type);
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
static void compute_size_bytes(ast::Node& node, SymbolDatabase& database)
|
||||
{
|
||||
for_each_node(node, ast::POSTORDER_TRAVERSAL, [&](ast::Node& node) {
|
||||
// Skip nodes that have already been processed.
|
||||
if(node.size_bytes > -1 || node.cannot_compute_size) {
|
||||
return ast::EXPLORE_CHILDREN;
|
||||
}
|
||||
|
||||
// Can't compute size recursively.
|
||||
node.cannot_compute_size = true;
|
||||
|
||||
switch(node.descriptor) {
|
||||
case ast::ARRAY: {
|
||||
ast::Array& array = node.as<ast::Array>();
|
||||
if(array.element_type->size_bytes > -1) {
|
||||
array.size_bytes = array.element_type->size_bytes * array.element_count;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ast::BITFIELD: {
|
||||
break;
|
||||
}
|
||||
case ast::BUILTIN: {
|
||||
ast::BuiltIn& built_in = node.as<ast::BuiltIn>();
|
||||
built_in.size_bytes = builtin_class_size(built_in.bclass);
|
||||
break;
|
||||
}
|
||||
case ast::FUNCTION: {
|
||||
break;
|
||||
}
|
||||
case ast::ENUM: {
|
||||
node.size_bytes = 4;
|
||||
break;
|
||||
}
|
||||
case ast::ERROR_NODE: {
|
||||
break;
|
||||
}
|
||||
case ast::STRUCT_OR_UNION: {
|
||||
node.size_bytes = node.size_bits / 8;
|
||||
break;
|
||||
}
|
||||
case ast::POINTER_OR_REFERENCE: {
|
||||
node.size_bytes = 4;
|
||||
break;
|
||||
}
|
||||
case ast::POINTER_TO_DATA_MEMBER: {
|
||||
break;
|
||||
}
|
||||
case ast::TYPE_NAME: {
|
||||
ast::TypeName& type_name = node.as<ast::TypeName>();
|
||||
DataType* resolved_type = database.data_types.symbol_from_handle(type_name.data_type_handle_unless_forward_declared());
|
||||
if(resolved_type) {
|
||||
ast::Node* resolved_node = resolved_type->type();
|
||||
CCC_ASSERT(resolved_node);
|
||||
if(resolved_node->size_bytes < 0 && !resolved_node->cannot_compute_size) {
|
||||
compute_size_bytes(*resolved_node, database);
|
||||
}
|
||||
type_name.size_bytes = resolved_node->size_bytes;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(node.size_bytes > -1) {
|
||||
node.cannot_compute_size = false;
|
||||
}
|
||||
|
||||
return ast::EXPLORE_CHILDREN;
|
||||
});
|
||||
}
|
||||
|
||||
static void detect_duplicate_functions(SymbolDatabase& database, const SymbolGroup& group)
|
||||
{
|
||||
std::vector<FunctionHandle> duplicate_functions;
|
||||
|
||||
for(Function& test_function : database.functions) {
|
||||
if(!test_function.address().valid() && !group.is_in_group(test_function)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find cases where there are two or more functions at the same address.
|
||||
auto functions_with_same_address = database.functions.handles_from_starting_address(test_function.address());
|
||||
if(functions_with_same_address.begin() == functions_with_same_address.end()) {
|
||||
continue;
|
||||
}
|
||||
if(++functions_with_same_address.begin() == functions_with_same_address.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try to figure out the address of the translation unit which the
|
||||
// version of the function that actually ended up in the linked binary
|
||||
// comes from. We can't just check which source file the symbol comes
|
||||
// from because it may be present in multiple.
|
||||
u32 source_file_address = UINT32_MAX;
|
||||
for(SourceFile& source_file : database.source_files) {
|
||||
if(source_file.address() < test_function.address()) {
|
||||
source_file_address = std::min(source_file.address().value, source_file_address);
|
||||
}
|
||||
}
|
||||
|
||||
if(source_file_address == UINT32_MAX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove the addresses from all the matching symbols from other
|
||||
// translation units.
|
||||
FunctionHandle best_handle;
|
||||
u32 best_offset = UINT32_MAX;
|
||||
for(const auto& [address, handle] : functions_with_same_address) {
|
||||
ccc::Function* function = database.functions.symbol_from_handle(handle);
|
||||
if(!function || !group.is_in_group(*function) || function->mangled_name() != test_function.mangled_name()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(address - source_file_address < best_offset) {
|
||||
if(best_handle.valid()) {
|
||||
duplicate_functions.emplace_back(best_handle);
|
||||
}
|
||||
best_handle = function->handle();
|
||||
best_offset = address - source_file_address;
|
||||
} else {
|
||||
duplicate_functions.emplace_back(function->handle());
|
||||
}
|
||||
}
|
||||
|
||||
for(FunctionHandle duplicate_function : duplicate_functions) {
|
||||
database.functions.move_symbol(duplicate_function, Address());
|
||||
}
|
||||
duplicate_functions.clear();
|
||||
}
|
||||
}
|
||||
|
||||
static void detect_fake_functions(SymbolDatabase& database, const std::map<u32, const mdebug::Symbol*>& external_functions, const SymbolGroup& group)
|
||||
{
|
||||
// Find cases where multiple fake function symbols were emitted for a given
|
||||
// address and cross-reference with the external symbol table to try and
|
||||
// find which one is the real one.
|
||||
s32 fake_function_count = 0;
|
||||
for(Function& function : database.functions) {
|
||||
if(!function.address().valid() || !group.is_in_group(function)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find cases where there are two or more functions at the same address.
|
||||
auto functions_with_same_address = database.functions.handles_from_starting_address(function.address());
|
||||
if(functions_with_same_address.begin() == functions_with_same_address.end()) {
|
||||
continue;
|
||||
}
|
||||
if(++functions_with_same_address.begin() == functions_with_same_address.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto external_function = external_functions.find(function.address().value);
|
||||
if(external_function == external_functions.end() || strcmp(function.mangled_name().c_str(), external_function->second->string) != 0) {
|
||||
database.functions.move_symbol(function.handle(), Address());
|
||||
|
||||
if(fake_function_count < 10) {
|
||||
CCC_WARN("Discarding address of function symbol '%s' as it is probably incorrect.", function.mangled_name().c_str());
|
||||
} else if(fake_function_count == 10) {
|
||||
CCC_WARN("Discarding more addresses of function symbols.");
|
||||
}
|
||||
|
||||
fake_function_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void destroy_optimized_out_functions(
|
||||
SymbolDatabase& database, const SymbolGroup& group)
|
||||
{
|
||||
bool marked = false;
|
||||
|
||||
for(Function& function : database.functions) {
|
||||
if(group.is_in_group(function) && !function.address().valid()) {
|
||||
function.mark_for_destruction();
|
||||
marked = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(marked) {
|
||||
// This will invalidate all pointers to symbols in the database.
|
||||
database.destroy_marked_symbols();
|
||||
}
|
||||
}
|
||||
|
||||
void fill_in_pointers_to_member_function_definitions(SymbolDatabase& database)
|
||||
{
|
||||
// Fill in pointers from member function declaration to corresponding definitions.
|
||||
for(Function& function : database.functions) {
|
||||
const std::string& qualified_name = function.name();
|
||||
std::string::size_type name_separator_pos = qualified_name.find_last_of("::");
|
||||
if(name_separator_pos == std::string::npos || name_separator_pos < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string function_name = qualified_name.substr(name_separator_pos + 1);
|
||||
|
||||
// This won't work for some template types.
|
||||
std::string::size_type type_separator_pos = qualified_name.find_last_of("::", name_separator_pos - 2);
|
||||
std::string type_name;
|
||||
if(type_separator_pos != std::string::npos) {
|
||||
type_name = qualified_name.substr(type_separator_pos + 1, name_separator_pos - type_separator_pos - 2);
|
||||
} else {
|
||||
type_name = qualified_name.substr(0, name_separator_pos - 1);
|
||||
}
|
||||
|
||||
for(const auto& name_handle : database.data_types.handles_from_name(type_name)) {
|
||||
DataType* data_type = database.data_types.symbol_from_handle(name_handle.second);
|
||||
if(!data_type || !data_type->type() || data_type->type()->descriptor != ast::STRUCT_OR_UNION) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ast::StructOrUnion& struct_or_union = data_type->type()->as<ast::StructOrUnion>();
|
||||
for(std::unique_ptr<ast::Node>& declaration : struct_or_union.member_functions) {
|
||||
if(declaration->name == function_name) {
|
||||
declaration->as<ast::Function>().definition_handle = function.handle().value;
|
||||
function.is_member_function_ish = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(function.is_member_function_ish) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
31
3rdparty/ccc/src/ccc/mdebug_importer.h
vendored
Normal file
31
3rdparty/ccc/src/ccc/mdebug_importer.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "mdebug_analysis.h"
|
||||
#include "mdebug_section.h"
|
||||
#include "symbol_database.h"
|
||||
|
||||
namespace ccc::mdebug {
|
||||
|
||||
// Perform all the main analysis passes on the mdebug symbol table and convert
|
||||
// it to a set of C++ ASTs.
|
||||
Result<void> import_symbol_table(
|
||||
SymbolDatabase& database,
|
||||
std::span<const u8> elf,
|
||||
s32 section_offset,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags,
|
||||
const DemanglerFunctions& demangler,
|
||||
const std::atomic_bool* interrupt);
|
||||
Result<void> import_files(SymbolDatabase& database, const AnalysisContext& context, const std::atomic_bool* interrupt);
|
||||
Result<void> import_file(SymbolDatabase& database, const mdebug::File& input, const AnalysisContext& context);
|
||||
|
||||
// Try to add pointers from member function declarations to their definitions
|
||||
// using a heuristic.
|
||||
void fill_in_pointers_to_member_function_definitions(SymbolDatabase& database);
|
||||
|
||||
}
|
||||
474
3rdparty/ccc/src/ccc/mdebug_section.cpp
vendored
Normal file
474
3rdparty/ccc/src/ccc/mdebug_section.cpp
vendored
Normal file
@@ -0,0 +1,474 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "mdebug_section.h"
|
||||
|
||||
namespace ccc::mdebug {
|
||||
|
||||
// MIPS debug symbol table headers.
|
||||
// See include/coff/sym.h from GNU binutils for more information.
|
||||
|
||||
CCC_PACKED_STRUCT(SymbolicHeader,
|
||||
/* 0x00 */ s16 magic;
|
||||
/* 0x02 */ s16 version_stamp;
|
||||
/* 0x04 */ s32 line_number_count;
|
||||
/* 0x08 */ s32 line_numbers_size_bytes;
|
||||
/* 0x0c */ s32 line_numbers_offset;
|
||||
/* 0x10 */ s32 dense_numbers_count;
|
||||
/* 0x14 */ s32 dense_numbers_offset;
|
||||
/* 0x18 */ s32 procedure_descriptor_count;
|
||||
/* 0x1c */ s32 procedure_descriptors_offset;
|
||||
/* 0x20 */ s32 local_symbol_count;
|
||||
/* 0x24 */ s32 local_symbols_offset;
|
||||
/* 0x28 */ s32 optimization_symbols_count;
|
||||
/* 0x2c */ s32 optimization_symbols_offset;
|
||||
/* 0x30 */ s32 auxiliary_symbol_count;
|
||||
/* 0x34 */ s32 auxiliary_symbols_offset;
|
||||
/* 0x38 */ s32 local_strings_size_bytes;
|
||||
/* 0x3c */ s32 local_strings_offset;
|
||||
/* 0x40 */ s32 external_strings_size_bytes;
|
||||
/* 0x44 */ s32 external_strings_offset;
|
||||
/* 0x48 */ s32 file_descriptor_count;
|
||||
/* 0x4c */ s32 file_descriptors_offset;
|
||||
/* 0x50 */ s32 relative_file_descriptor_count;
|
||||
/* 0x54 */ s32 relative_file_descriptors_offset;
|
||||
/* 0x58 */ s32 external_symbols_count;
|
||||
/* 0x5c */ s32 external_symbols_offset;
|
||||
)
|
||||
|
||||
CCC_PACKED_STRUCT(FileDescriptor,
|
||||
/* 0x00 */ u32 address;
|
||||
/* 0x04 */ s32 file_path_string_offset;
|
||||
/* 0x08 */ s32 strings_offset;
|
||||
/* 0x0c */ s32 cb_ss;
|
||||
/* 0x10 */ s32 isym_base;
|
||||
/* 0x14 */ s32 symbol_count;
|
||||
/* 0x18 */ s32 line_number_entry_index_base;
|
||||
/* 0x1c */ s32 cline;
|
||||
/* 0x20 */ s32 optimization_entry_index_base;
|
||||
/* 0x24 */ s32 copt;
|
||||
/* 0x28 */ u16 ipd_first;
|
||||
/* 0x2a */ u16 procedure_descriptor_count;
|
||||
/* 0x2c */ s32 iaux_base;
|
||||
/* 0x30 */ s32 caux;
|
||||
/* 0x34 */ s32 rfd_base;
|
||||
/* 0x38 */ s32 crfd;
|
||||
/* 0x3c */ u32 lang : 5;
|
||||
/* 0x3c */ u32 f_merge : 1;
|
||||
/* 0x3c */ u32 f_readin : 1;
|
||||
/* 0x3c */ u32 f_big_endian : 1;
|
||||
/* 0x3c */ u32 reserved_1 : 22;
|
||||
/* 0x40 */ s32 line_number_offset;
|
||||
/* 0x44 */ s32 cb_line;
|
||||
)
|
||||
static_assert(sizeof(FileDescriptor) == 0x48);
|
||||
|
||||
CCC_PACKED_STRUCT(SymbolHeader,
|
||||
/* 0x0 */ u32 iss;
|
||||
/* 0x4 */ u32 value;
|
||||
/* 0x8 */ u32 st : 6;
|
||||
/* 0x8 */ u32 sc : 5;
|
||||
/* 0x8 */ u32 reserved : 1;
|
||||
/* 0x8 */ u32 index : 20;
|
||||
)
|
||||
static_assert(sizeof(SymbolHeader) == 0xc);
|
||||
|
||||
CCC_PACKED_STRUCT(ExternalSymbolHeader,
|
||||
/* 0x0 */ u16 flags;
|
||||
/* 0x2 */ s16 ifd;
|
||||
/* 0x4 */ SymbolHeader symbol;
|
||||
)
|
||||
static_assert(sizeof(ExternalSymbolHeader) == 0x10);
|
||||
|
||||
static void print_symbol(FILE* out, const Symbol& symbol);
|
||||
static void print_procedure_descriptor(FILE* out, const ProcedureDescriptor& procedure_descriptor);
|
||||
static Result<s32> get_corruption_fixing_fudge_offset(s32 section_offset, const SymbolicHeader& hdrr);
|
||||
static Result<Symbol> get_symbol(const SymbolHeader& header, std::span<const u8> elf, s32 strings_offset);
|
||||
|
||||
Result<void> SymbolTableReader::init(std::span<const u8> elf, s32 section_offset)
|
||||
{
|
||||
m_elf = elf;
|
||||
m_section_offset = section_offset;
|
||||
|
||||
m_hdrr = get_unaligned<SymbolicHeader>(m_elf, m_section_offset);
|
||||
CCC_CHECK(m_hdrr != nullptr, "MIPS debug section header out of bounds.");
|
||||
CCC_CHECK(m_hdrr->magic == 0x7009, "Invalid symbolic header.");
|
||||
|
||||
Result<s32> fudge_offset = get_corruption_fixing_fudge_offset(m_section_offset, *m_hdrr);
|
||||
CCC_RETURN_IF_ERROR(fudge_offset);
|
||||
m_fudge_offset = *fudge_offset;
|
||||
|
||||
m_ready = true;
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
s32 SymbolTableReader::file_count() const
|
||||
{
|
||||
CCC_ASSERT(m_ready);
|
||||
return m_hdrr->file_descriptor_count;
|
||||
}
|
||||
|
||||
Result<File> SymbolTableReader::parse_file(s32 index) const
|
||||
{
|
||||
CCC_ASSERT(m_ready);
|
||||
|
||||
File file;
|
||||
|
||||
u64 fd_offset = m_hdrr->file_descriptors_offset + index * sizeof(FileDescriptor);
|
||||
const FileDescriptor* fd_header = get_unaligned<FileDescriptor>(m_elf, fd_offset + m_fudge_offset);
|
||||
CCC_CHECK(fd_header != nullptr, "MIPS debug file descriptor out of bounds.");
|
||||
CCC_CHECK(fd_header->f_big_endian == 0, "Not little endian or bad file descriptor table.");
|
||||
|
||||
file.address = fd_header->address;
|
||||
|
||||
s32 rel_raw_path_offset = fd_header->strings_offset + fd_header->file_path_string_offset;
|
||||
s32 raw_path_offset = m_hdrr->local_strings_offset + rel_raw_path_offset + m_fudge_offset;
|
||||
std::optional<std::string_view> command_line_path = get_string(m_elf, raw_path_offset);
|
||||
if(command_line_path.has_value()) {
|
||||
file.command_line_path = *command_line_path;
|
||||
}
|
||||
|
||||
// Parse local symbols.
|
||||
for(s64 j = 0; j < fd_header->symbol_count; j++) {
|
||||
u64 rel_symbol_offset = (fd_header->isym_base + j) * sizeof(SymbolHeader);
|
||||
u64 symbol_offset = m_hdrr->local_symbols_offset + rel_symbol_offset + m_fudge_offset;
|
||||
const SymbolHeader* symbol_header = get_unaligned<SymbolHeader>(m_elf, symbol_offset);
|
||||
CCC_CHECK(symbol_header != nullptr, "Symbol header out of bounds.");
|
||||
|
||||
s32 strings_offset = m_hdrr->local_strings_offset + fd_header->strings_offset + m_fudge_offset;
|
||||
Result<Symbol> sym = get_symbol(*symbol_header, m_elf, strings_offset);
|
||||
CCC_RETURN_IF_ERROR(sym);
|
||||
|
||||
bool string_offset_equal = (s32) symbol_header->iss == fd_header->file_path_string_offset;
|
||||
if(file.working_dir.empty() && string_offset_equal && sym->is_stabs() && sym->code() == N_SO && file.symbols.size() > 2) {
|
||||
const Symbol& working_dir = file.symbols.back();
|
||||
if(working_dir.is_stabs() && working_dir.code() == N_SO) {
|
||||
file.working_dir = working_dir.string;
|
||||
}
|
||||
}
|
||||
|
||||
file.symbols.emplace_back(std::move(*sym));
|
||||
}
|
||||
|
||||
// Parse procedure descriptors.
|
||||
for(s64 i = 0; i < fd_header->procedure_descriptor_count; i++) {
|
||||
u64 rel_procedure_offset = (fd_header->ipd_first + i) * sizeof(ProcedureDescriptor);
|
||||
u64 procedure_offset = m_hdrr->procedure_descriptors_offset + rel_procedure_offset + m_fudge_offset;
|
||||
const ProcedureDescriptor* procedure_descriptor = get_unaligned<ProcedureDescriptor>(m_elf, procedure_offset);
|
||||
CCC_CHECK(procedure_descriptor != nullptr, "Procedure descriptor out of bounds.");
|
||||
|
||||
CCC_CHECK(procedure_descriptor->symbol_index < file.symbols.size(), "Symbol index out of bounds.");
|
||||
file.symbols[procedure_descriptor->symbol_index].procedure_descriptor = procedure_descriptor;
|
||||
}
|
||||
|
||||
|
||||
file.full_path = merge_paths(file.working_dir, file.command_line_path);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
Result<std::vector<Symbol>> SymbolTableReader::parse_external_symbols() const
|
||||
{
|
||||
CCC_ASSERT(m_ready);
|
||||
|
||||
std::vector<Symbol> external_symbols;
|
||||
for(s64 i = 0; i < m_hdrr->external_symbols_count; i++) {
|
||||
u64 sym_offset = m_hdrr->external_symbols_offset + i * sizeof(ExternalSymbolHeader);
|
||||
const ExternalSymbolHeader* external_header = get_unaligned<ExternalSymbolHeader>(m_elf, sym_offset + m_fudge_offset);
|
||||
CCC_CHECK(external_header != nullptr, "External header out of bounds.");
|
||||
|
||||
Result<Symbol> sym = get_symbol(external_header->symbol, m_elf, m_hdrr->external_strings_offset + m_fudge_offset);
|
||||
CCC_RETURN_IF_ERROR(sym);
|
||||
external_symbols.emplace_back(std::move(*sym));
|
||||
}
|
||||
|
||||
return external_symbols;
|
||||
}
|
||||
|
||||
void SymbolTableReader::print_header(FILE* dest) const
|
||||
{
|
||||
CCC_ASSERT(m_ready);
|
||||
|
||||
fprintf(dest, "Symbolic Header, magic = %hx, vstamp = %hx:\n",
|
||||
(u16) m_hdrr->magic,
|
||||
(u16) m_hdrr->version_stamp);
|
||||
fprintf(dest, "\n");
|
||||
fprintf(dest, " Offset Size (Bytes) Count\n");
|
||||
fprintf(dest, " ------ ------------ -----\n");
|
||||
fprintf(dest, " Line Numbers 0x%-8x " "0x%-8x " "%-8d\n",
|
||||
(u32) m_hdrr->line_numbers_offset,
|
||||
(u32) m_hdrr->line_numbers_size_bytes,
|
||||
m_hdrr->line_number_count);
|
||||
fprintf(dest, " Dense Numbers 0x%-8x " "0x%-8x " "%-8d\n",
|
||||
(u32) m_hdrr->dense_numbers_offset,
|
||||
(u32) m_hdrr->dense_numbers_count * 8,
|
||||
m_hdrr->dense_numbers_count);
|
||||
fprintf(dest, " Procedure Descriptors 0x%-8x " "0x%-8x " "%-8d\n",
|
||||
(u32) m_hdrr->procedure_descriptors_offset,
|
||||
(u32) m_hdrr->procedure_descriptor_count * (u32) sizeof(ProcedureDescriptor),
|
||||
m_hdrr->procedure_descriptor_count);
|
||||
fprintf(dest, " Local Symbols 0x%-8x " "0x%-8x " "%-8d\n",
|
||||
(u32) m_hdrr->local_symbols_offset,
|
||||
(u32) m_hdrr->local_symbol_count * (u32) sizeof(SymbolHeader),
|
||||
m_hdrr->local_symbol_count);
|
||||
fprintf(dest, " Optimization Symbols 0x%-8x " "- " "%-8d\n",
|
||||
(u32) m_hdrr->optimization_symbols_offset,
|
||||
m_hdrr->optimization_symbols_count);
|
||||
fprintf(dest, " Auxiliary Symbols 0x%-8x " "0x%-8x " "%-8d\n",
|
||||
(u32) m_hdrr->auxiliary_symbols_offset,
|
||||
(u32) m_hdrr->auxiliary_symbol_count * 4,
|
||||
m_hdrr->auxiliary_symbol_count);
|
||||
fprintf(dest, " Local Strings 0x%-8x " "0x%-8x " "-\n",
|
||||
(u32) m_hdrr->local_strings_offset,
|
||||
(u32) m_hdrr->local_strings_size_bytes);
|
||||
fprintf(dest, " External Strings 0x%-8x " "0x%-8x " "-\n",
|
||||
(u32) m_hdrr->external_strings_offset,
|
||||
(u32) m_hdrr->external_strings_size_bytes);
|
||||
fprintf(dest, " File Descriptors 0x%-8x " "0x%-8x " "%-8d\n",
|
||||
(u32) m_hdrr->file_descriptors_offset,
|
||||
(u32) m_hdrr->file_descriptor_count * (u32) sizeof(FileDescriptor),
|
||||
m_hdrr->file_descriptor_count);
|
||||
fprintf(dest, " Relative File Descriptors 0x%-8x " "0x%-8x " "%-8d\n",
|
||||
(u32) m_hdrr->relative_file_descriptors_offset,
|
||||
(u32) m_hdrr->relative_file_descriptor_count * 4,
|
||||
m_hdrr->relative_file_descriptor_count);
|
||||
fprintf(dest, " External Symbols 0x%-8x " "0x%-8x " "%-8d\n",
|
||||
(u32) m_hdrr->external_symbols_offset,
|
||||
(u32) m_hdrr->external_symbols_count * 16,
|
||||
m_hdrr->external_symbols_count);
|
||||
}
|
||||
|
||||
Result<void> SymbolTableReader::print_symbols(FILE* out, bool print_locals, bool print_procedure_descriptors, bool print_externals) const
|
||||
{
|
||||
if(print_locals || print_procedure_descriptors) {
|
||||
s32 count = file_count();
|
||||
for(s32 i = 0; i < count; i++) {
|
||||
Result<File> file = parse_file(i);
|
||||
CCC_RETURN_IF_ERROR(file);
|
||||
|
||||
fprintf(out, "FILE %s:\n", file->command_line_path.c_str());
|
||||
for(const Symbol& symbol : file->symbols) {
|
||||
if(print_locals || symbol.procedure_descriptor) {
|
||||
print_symbol(out, symbol);
|
||||
}
|
||||
if(print_procedure_descriptors && symbol.procedure_descriptor) {
|
||||
print_procedure_descriptor(out, *symbol.procedure_descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(print_externals) {
|
||||
fprintf(out, "EXTERNAL SYMBOLS:\n");
|
||||
Result<std::vector<Symbol>> external_symbols = parse_external_symbols();
|
||||
CCC_RETURN_IF_ERROR(external_symbols);
|
||||
for(const Symbol& symbol : *external_symbols) {
|
||||
print_symbol(out, symbol);
|
||||
}
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
static void print_symbol(FILE* out, const Symbol& symbol)
|
||||
{
|
||||
fprintf(out, " %8x ", symbol.value);
|
||||
|
||||
const char* symbol_type_str = symbol_type(symbol.symbol_type);
|
||||
if(symbol_type_str) {
|
||||
fprintf(out, "%-11s ", symbol_type_str);
|
||||
} else {
|
||||
fprintf(out, "ST(%7u) ", (u32) symbol.symbol_type);
|
||||
}
|
||||
|
||||
const char* symbol_class_str = symbol_class(symbol.symbol_class);
|
||||
if(symbol_class_str) {
|
||||
fprintf(out, "%-4s ", symbol_class_str);
|
||||
} else if ((u32) symbol.symbol_class == 0) {
|
||||
fprintf(out, " ");
|
||||
} else {
|
||||
fprintf(out, "SC(%4u) ", (u32) symbol.symbol_class);
|
||||
}
|
||||
|
||||
if(symbol.is_stabs()) {
|
||||
fprintf(out, "%-8s ", stabs_code_to_string(symbol.code()));
|
||||
} else {
|
||||
fprintf(out, "SI(%4u) ", symbol.index);
|
||||
}
|
||||
|
||||
fprintf(out, "%s\n", symbol.string);
|
||||
}
|
||||
|
||||
static void print_procedure_descriptor(FILE* out, const ProcedureDescriptor& procedure_descriptor)
|
||||
{
|
||||
fprintf(out, " Address 0x%08x\n", procedure_descriptor.address);
|
||||
fprintf(out, " Symbol Index %d\n", procedure_descriptor.symbol_index);
|
||||
fprintf(out, " Line Number Entry Index %d\n", procedure_descriptor.line_number_entry_index);
|
||||
fprintf(out, " Saved Register Mask 0x%08x\n", procedure_descriptor.saved_register_mask);
|
||||
fprintf(out, " Saved Register Offset %d\n", procedure_descriptor.saved_register_offset);
|
||||
fprintf(out, " Optimization Entry Index %d\n", procedure_descriptor.optimization_entry_index);
|
||||
fprintf(out, " Saved Float Register Mask 0x%08x\n", procedure_descriptor.saved_float_register_mask);
|
||||
fprintf(out, " Saved Float Register Offset %d\n", procedure_descriptor.saved_float_register_offset);
|
||||
fprintf(out, " Frame Size %d\n", procedure_descriptor.frame_size);
|
||||
fprintf(out, " Frame Pointer Register %hd\n", procedure_descriptor.frame_pointer_register);
|
||||
fprintf(out, " Return PC Register %hd\n", procedure_descriptor.return_pc_register);
|
||||
fprintf(out, " Line Number Low %d\n", procedure_descriptor.line_number_low);
|
||||
fprintf(out, " Line Number High %d\n", procedure_descriptor.line_number_high);
|
||||
fprintf(out, " Line Number Offset %d\n", procedure_descriptor.line_number_offset);
|
||||
}
|
||||
|
||||
static Result<s32> get_corruption_fixing_fudge_offset(s32 section_offset, const SymbolicHeader& hdrr)
|
||||
{
|
||||
// GCC will always put the first part of the symbol table right after the
|
||||
// header, so if the header says it's somewhere else we know the section has
|
||||
// probably been moved without updating its contents.
|
||||
s32 right_after_header = INT32_MAX;
|
||||
if(hdrr.line_numbers_offset > 0) right_after_header = std::min(hdrr.line_numbers_offset, right_after_header);
|
||||
if(hdrr.dense_numbers_offset > 0) right_after_header = std::min(hdrr.dense_numbers_offset, right_after_header);
|
||||
if(hdrr.procedure_descriptors_offset > 0) right_after_header = std::min(hdrr.procedure_descriptors_offset, right_after_header);
|
||||
if(hdrr.local_symbols_offset > 0) right_after_header = std::min(hdrr.local_symbols_offset, right_after_header);
|
||||
if(hdrr.optimization_symbols_offset > 0) right_after_header = std::min(hdrr.optimization_symbols_offset, right_after_header);
|
||||
if(hdrr.auxiliary_symbols_offset > 0) right_after_header = std::min(hdrr.auxiliary_symbols_offset, right_after_header);
|
||||
if(hdrr.local_strings_offset > 0) right_after_header = std::min(hdrr.local_strings_offset, right_after_header);
|
||||
if(hdrr.external_strings_offset > 0) right_after_header = std::min(hdrr.external_strings_offset, right_after_header);
|
||||
if(hdrr.file_descriptors_offset > 0) right_after_header = std::min(hdrr.file_descriptors_offset, right_after_header);
|
||||
if(hdrr.relative_file_descriptors_offset > 0) right_after_header = std::min(hdrr.relative_file_descriptors_offset, right_after_header);
|
||||
if(hdrr.external_symbols_offset > 0) right_after_header = std::min(hdrr.external_symbols_offset, right_after_header);
|
||||
|
||||
CCC_CHECK(right_after_header >= 0 && right_after_header < INT32_MAX, "Invalid symbolic header.");
|
||||
|
||||
// Figure out how much we need to adjust all the file offsets by.
|
||||
s32 fudge_offset = section_offset - (right_after_header - sizeof(SymbolicHeader));
|
||||
if(fudge_offset != 0) {
|
||||
CCC_WARN("The .mdebug section was moved without updating its contents. Adjusting file offsets by %d bytes.", fudge_offset);
|
||||
}
|
||||
|
||||
return fudge_offset;
|
||||
}
|
||||
|
||||
static Result<Symbol> get_symbol(const SymbolHeader& header, std::span<const u8> elf, s32 strings_offset)
|
||||
{
|
||||
Symbol symbol;
|
||||
|
||||
std::optional<std::string_view> string = get_string(elf, strings_offset + header.iss);
|
||||
CCC_CHECK(string.has_value(), "Symbol has invalid string.");
|
||||
symbol.string = string->data();
|
||||
|
||||
symbol.value = header.value;
|
||||
symbol.symbol_type = (SymbolType) header.st;
|
||||
symbol.symbol_class = (SymbolClass) header.sc;
|
||||
symbol.index = header.index;
|
||||
|
||||
if(symbol.is_stabs()) {
|
||||
CCC_CHECK(stabs_code_to_string(symbol.code()) != nullptr, "Bad stabs symbol code '%x'.", symbol.code());
|
||||
}
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
const char* symbol_type(SymbolType type)
|
||||
{
|
||||
switch(type) {
|
||||
case SymbolType::NIL: return "NIL";
|
||||
case SymbolType::GLOBAL: return "GLOBAL";
|
||||
case SymbolType::STATIC: return "STATIC";
|
||||
case SymbolType::PARAM: return "PARAM";
|
||||
case SymbolType::LOCAL: return "LOCAL";
|
||||
case SymbolType::LABEL: return "LABEL";
|
||||
case SymbolType::PROC: return "PROC";
|
||||
case SymbolType::BLOCK: return "BLOCK";
|
||||
case SymbolType::END: return "END";
|
||||
case SymbolType::MEMBER: return "MEMBER";
|
||||
case SymbolType::TYPEDEF: return "TYPEDEF";
|
||||
case SymbolType::FILE_SYMBOL: return "FILE";
|
||||
case SymbolType::STATICPROC: return "STATICPROC";
|
||||
case SymbolType::CONSTANT: return "CONSTANT";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* symbol_class(SymbolClass symbol_class)
|
||||
{
|
||||
switch(symbol_class) {
|
||||
case SymbolClass::NIL: return "NIL";
|
||||
case SymbolClass::TEXT: return "TEXT";
|
||||
case SymbolClass::DATA: return "DATA";
|
||||
case SymbolClass::BSS: return "BSS";
|
||||
case SymbolClass::REGISTER: return "REGISTER";
|
||||
case SymbolClass::ABS: return "ABS";
|
||||
case SymbolClass::UNDEFINED: return "UNDEFINED";
|
||||
case SymbolClass::LOCAL: return "LOCAL";
|
||||
case SymbolClass::BITS: return "BITS";
|
||||
case SymbolClass::DBX: return "DBX";
|
||||
case SymbolClass::REG_IMAGE: return "REG_IMAGE";
|
||||
case SymbolClass::INFO: return "INFO";
|
||||
case SymbolClass::USER_STRUCT: return "USER_STRUCT";
|
||||
case SymbolClass::SDATA: return "SDATA";
|
||||
case SymbolClass::SBSS: return "SBSS";
|
||||
case SymbolClass::RDATA: return "RDATA";
|
||||
case SymbolClass::VAR: return "VAR";
|
||||
case SymbolClass::COMMON: return "COMMON";
|
||||
case SymbolClass::SCOMMON: return "SCOMMON";
|
||||
case SymbolClass::VAR_REGISTER: return "VAR_REGISTER";
|
||||
case SymbolClass::VARIANT: return "VARIANT";
|
||||
case SymbolClass::SUNDEFINED: return "SUNDEFINED";
|
||||
case SymbolClass::INIT: return "INIT";
|
||||
case SymbolClass::BASED_VAR: return "BASED_VAR";
|
||||
case SymbolClass::XDATA: return "XDATA";
|
||||
case SymbolClass::PDATA: return "PDATA";
|
||||
case SymbolClass::FINI: return "FINI";
|
||||
case SymbolClass::NONGP: return "NONGP";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* stabs_code_to_string(StabsCode code)
|
||||
{
|
||||
switch(code) {
|
||||
case STAB: return "STAB";
|
||||
case N_GSYM: return "GSYM";
|
||||
case N_FNAME: return "FNAME";
|
||||
case N_FUN: return "FUN";
|
||||
case N_STSYM: return "STSYM";
|
||||
case N_LCSYM: return "LCSYM";
|
||||
case N_MAIN: return "MAIN";
|
||||
case N_PC: return "PC";
|
||||
case N_NSYMS: return "NSYMS";
|
||||
case N_NOMAP: return "NOMAP";
|
||||
case N_OBJ: return "OBJ";
|
||||
case N_OPT: return "OPT";
|
||||
case N_RSYM: return "RSYM";
|
||||
case N_M2C: return "M2C";
|
||||
case N_SLINE: return "SLINE";
|
||||
case N_DSLINE: return "DSLINE";
|
||||
case N_BSLINE: return "BSLINE";
|
||||
case N_EFD: return "EFD";
|
||||
case N_EHDECL: return "EHDECL";
|
||||
case N_CATCH: return "CATCH";
|
||||
case N_SSYM: return "SSYM";
|
||||
case N_SO: return "SO";
|
||||
case N_LSYM: return "LSYM";
|
||||
case N_BINCL: return "BINCL";
|
||||
case N_SOL: return "SOL";
|
||||
case N_PSYM: return "PSYM";
|
||||
case N_EINCL: return "EINCL";
|
||||
case N_ENTRY: return "ENTRY";
|
||||
case N_LBRAC: return "LBRAC";
|
||||
case N_EXCL: return "EXCL";
|
||||
case N_SCOPE: return "SCOPE";
|
||||
case N_RBRAC: return "RBRAC";
|
||||
case N_BCOMM: return "BCOMM";
|
||||
case N_ECOMM: return "ECOMM";
|
||||
case N_ECOML: return "ECOML";
|
||||
case N_NBTEXT: return "NBTEXT";
|
||||
case N_NBDATA: return "NBDATA";
|
||||
case N_NBBSS: return "NBBSS";
|
||||
case N_NBSTS: return "NBSTS";
|
||||
case N_NBLCS: return "NBLCS";
|
||||
case N_LENG: return "LENG";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
176
3rdparty/ccc/src/ccc/mdebug_section.h
vendored
Normal file
176
3rdparty/ccc/src/ccc/mdebug_section.h
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util.h"
|
||||
|
||||
namespace ccc::mdebug {
|
||||
|
||||
struct SymbolicHeader;
|
||||
|
||||
enum class SymbolType : u32 {
|
||||
NIL = 0,
|
||||
GLOBAL = 1,
|
||||
STATIC = 2,
|
||||
PARAM = 3,
|
||||
LOCAL = 4,
|
||||
LABEL = 5,
|
||||
PROC = 6,
|
||||
BLOCK = 7,
|
||||
END = 8,
|
||||
MEMBER = 9,
|
||||
TYPEDEF = 10,
|
||||
FILE_SYMBOL = 11,
|
||||
STATICPROC = 14,
|
||||
CONSTANT = 15
|
||||
};
|
||||
|
||||
enum class SymbolClass : u32 {
|
||||
NIL = 0,
|
||||
TEXT = 1,
|
||||
DATA = 2,
|
||||
BSS = 3,
|
||||
REGISTER = 4,
|
||||
ABS = 5,
|
||||
UNDEFINED = 6,
|
||||
LOCAL = 7,
|
||||
BITS = 8,
|
||||
DBX = 9,
|
||||
REG_IMAGE = 10,
|
||||
INFO = 11,
|
||||
USER_STRUCT = 12,
|
||||
SDATA = 13,
|
||||
SBSS = 14,
|
||||
RDATA = 15,
|
||||
VAR = 16,
|
||||
COMMON = 17,
|
||||
SCOMMON = 18,
|
||||
VAR_REGISTER = 19,
|
||||
VARIANT = 20,
|
||||
SUNDEFINED = 21,
|
||||
INIT = 22,
|
||||
BASED_VAR = 23,
|
||||
XDATA = 24,
|
||||
PDATA = 25,
|
||||
FINI = 26,
|
||||
NONGP = 27
|
||||
};
|
||||
|
||||
// See stab.def from gcc for documentation on what all these are.
|
||||
enum StabsCode {
|
||||
STAB = 0x00,
|
||||
N_GSYM = 0x20,
|
||||
N_FNAME = 0x22,
|
||||
N_FUN = 0x24,
|
||||
N_STSYM = 0x26,
|
||||
N_LCSYM = 0x28,
|
||||
N_MAIN = 0x2a,
|
||||
N_PC = 0x30,
|
||||
N_NSYMS = 0x32,
|
||||
N_NOMAP = 0x34,
|
||||
N_OBJ = 0x38,
|
||||
N_OPT = 0x3c,
|
||||
N_RSYM = 0x40,
|
||||
N_M2C = 0x42,
|
||||
N_SLINE = 0x44,
|
||||
N_DSLINE = 0x46,
|
||||
N_BSLINE = 0x48,
|
||||
N_EFD = 0x4a,
|
||||
N_EHDECL = 0x50,
|
||||
N_CATCH = 0x54,
|
||||
N_SSYM = 0x60,
|
||||
N_SO = 0x64,
|
||||
N_LSYM = 0x80,
|
||||
N_BINCL = 0x82,
|
||||
N_SOL = 0x84,
|
||||
N_PSYM = 0xa0,
|
||||
N_EINCL = 0xa2,
|
||||
N_ENTRY = 0xa4,
|
||||
N_LBRAC = 0xc0,
|
||||
N_EXCL = 0xc2,
|
||||
N_SCOPE = 0xc4,
|
||||
N_RBRAC = 0xe0,
|
||||
N_BCOMM = 0xe2,
|
||||
N_ECOMM = 0xe4,
|
||||
N_ECOML = 0xe8,
|
||||
N_NBTEXT = 0xf0,
|
||||
N_NBDATA = 0xf2,
|
||||
N_NBBSS = 0xf4,
|
||||
N_NBSTS = 0xf6,
|
||||
N_NBLCS = 0xf8,
|
||||
N_LENG = 0xfe
|
||||
};
|
||||
|
||||
CCC_PACKED_STRUCT(ProcedureDescriptor,
|
||||
/* 0x00 */ u32 address;
|
||||
/* 0x04 */ u32 symbol_index;
|
||||
/* 0x08 */ s32 line_number_entry_index;
|
||||
/* 0x0c */ s32 saved_register_mask;
|
||||
/* 0x10 */ s32 saved_register_offset;
|
||||
/* 0x14 */ s32 optimization_entry_index;
|
||||
/* 0x18 */ s32 saved_float_register_mask;
|
||||
/* 0x1c */ s32 saved_float_register_offset;
|
||||
/* 0x20 */ s32 frame_size;
|
||||
/* 0x24 */ s16 frame_pointer_register;
|
||||
/* 0x26 */ s16 return_pc_register;
|
||||
/* 0x28 */ s32 line_number_low;
|
||||
/* 0x2c */ s32 line_number_high;
|
||||
/* 0x30 */ u32 line_number_offset;
|
||||
)
|
||||
static_assert(sizeof(ProcedureDescriptor) == 0x34);
|
||||
|
||||
struct Symbol {
|
||||
u32 value;
|
||||
SymbolType symbol_type;
|
||||
SymbolClass symbol_class;
|
||||
u32 index;
|
||||
const char* string;
|
||||
const ProcedureDescriptor* procedure_descriptor = nullptr;
|
||||
|
||||
bool is_stabs() const {
|
||||
return (index & 0xfff00) == 0x8f300;
|
||||
}
|
||||
|
||||
StabsCode code() const {
|
||||
return (StabsCode) (index - 0x8f300);
|
||||
}
|
||||
};
|
||||
|
||||
struct File {
|
||||
std::vector<Symbol> symbols;
|
||||
u32 address = 0;
|
||||
std::string working_dir; // The working directory of gcc.
|
||||
std::string command_line_path; // The source file path passed on the command line to gcc.
|
||||
std::string full_path; // The full combined path.
|
||||
};
|
||||
|
||||
class SymbolTableReader {
|
||||
public:
|
||||
Result<void> init(std::span<const u8> elf, s32 section_offset);
|
||||
|
||||
s32 file_count() const;
|
||||
Result<File> parse_file(s32 index) const;
|
||||
Result<std::vector<Symbol>> parse_external_symbols() const;
|
||||
|
||||
void print_header(FILE* out) const;
|
||||
Result<void> print_symbols(FILE* out, bool print_locals, bool print_procedure_descriptors, bool print_externals) const;
|
||||
|
||||
protected:
|
||||
bool m_ready = false;
|
||||
|
||||
std::span<const u8> m_elf;
|
||||
s32 m_section_offset;
|
||||
|
||||
// If the .mdebug section was moved without updating its contents all the
|
||||
// absolute file offsets stored within will be incorrect by a fixed amount.
|
||||
s32 m_fudge_offset;
|
||||
|
||||
const SymbolicHeader* m_hdrr;
|
||||
};
|
||||
|
||||
const char* symbol_type(SymbolType type);
|
||||
const char* symbol_class(SymbolClass symbol_class);
|
||||
const char* stabs_code_to_string(StabsCode code);
|
||||
|
||||
}
|
||||
220
3rdparty/ccc/src/ccc/mdebug_symbols.cpp
vendored
Normal file
220
3rdparty/ccc/src/ccc/mdebug_symbols.cpp
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "mdebug_symbols.h"
|
||||
|
||||
#include "importer_flags.h"
|
||||
|
||||
namespace ccc::mdebug {
|
||||
|
||||
static void mark_duplicate_symbols(std::vector<ParsedSymbol>& symbols);
|
||||
|
||||
Result<std::vector<ParsedSymbol>> parse_symbols(const std::vector<mdebug::Symbol>& input, u32& importer_flags)
|
||||
{
|
||||
std::vector<ParsedSymbol> output;
|
||||
std::string prefix;
|
||||
for(const mdebug::Symbol& symbol : input) {
|
||||
if(symbol.is_stabs()) {
|
||||
switch(symbol.code()) {
|
||||
case mdebug::N_GSYM: // Global variable
|
||||
case mdebug::N_FUN: // Function
|
||||
case mdebug::N_STSYM: // Data section static global variable
|
||||
case mdebug::N_LCSYM: // BSS section static global variable
|
||||
case mdebug::N_RSYM: // Register variable
|
||||
case mdebug::N_LSYM: // Automatic variable or type definition
|
||||
case mdebug::N_PSYM: { // Parameter variable
|
||||
// Some STABS symbols are split between multiple strings.
|
||||
if(symbol.string[0] != '\0') {
|
||||
if(symbol.string[strlen(symbol.string) - 1] == '\\') {
|
||||
prefix += std::string(symbol.string, symbol.string + strlen(symbol.string) - 1);
|
||||
} else {
|
||||
std::string merged_string;
|
||||
const char* string;
|
||||
if(!prefix.empty()) {
|
||||
merged_string = prefix + symbol.string;
|
||||
string = merged_string.c_str();
|
||||
prefix.clear();
|
||||
} else {
|
||||
string = symbol.string;
|
||||
}
|
||||
|
||||
const char* input = string;
|
||||
Result<StabsSymbol> parse_result = parse_stabs_symbol(input);
|
||||
if(parse_result.success()) {
|
||||
if(*input != '\0') {
|
||||
if(importer_flags & STRICT_PARSING) {
|
||||
return CCC_FAILURE("Unknown data '%s' at the end of the '%s' stab.", input, parse_result->name.c_str());
|
||||
} else {
|
||||
CCC_WARN("Unknown data '%s' at the end of the '%s' stab.", input, parse_result->name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
ParsedSymbol& parsed = output.emplace_back();
|
||||
parsed.type = ParsedSymbolType::NAME_COLON_TYPE;
|
||||
parsed.raw = &symbol;
|
||||
parsed.name_colon_type = std::move(*parse_result);
|
||||
} else if(parse_result.error().message == STAB_TRUNCATED_ERROR_MESSAGE) {
|
||||
// Symbol truncated due to a GCC bug. Report a
|
||||
// warning and try to tolerate further faults
|
||||
// caused as a result of this.
|
||||
CCC_WARN("%s Symbol string: %s", STAB_TRUNCATED_ERROR_MESSAGE, string);
|
||||
importer_flags &= ~STRICT_PARSING;
|
||||
} else {
|
||||
return CCC_FAILURE("%s Symbol string: %s",
|
||||
parse_result.error().message.c_str(), string);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CCC_CHECK(prefix.empty(), "Invalid STABS continuation.");
|
||||
if(symbol.code() == mdebug::N_FUN) {
|
||||
ParsedSymbol& func_end = output.emplace_back();
|
||||
func_end.type = ParsedSymbolType::FUNCTION_END;
|
||||
func_end.raw = &symbol;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case mdebug::N_SOL: { // Sub-source file
|
||||
ParsedSymbol& sub = output.emplace_back();
|
||||
sub.type = ParsedSymbolType::SUB_SOURCE_FILE;
|
||||
sub.raw = &symbol;
|
||||
break;
|
||||
}
|
||||
case mdebug::N_LBRAC: { // Begin block
|
||||
ParsedSymbol& begin_block = output.emplace_back();
|
||||
begin_block.type = ParsedSymbolType::LBRAC;
|
||||
begin_block.raw = &symbol;
|
||||
break;
|
||||
}
|
||||
case mdebug::N_RBRAC: { // End block
|
||||
ParsedSymbol& end_block = output.emplace_back();
|
||||
end_block.type = ParsedSymbolType::RBRAC;
|
||||
end_block.raw = &symbol;
|
||||
break;
|
||||
}
|
||||
case mdebug::N_SO: { // Source filename
|
||||
ParsedSymbol& so_symbol = output.emplace_back();
|
||||
so_symbol.type = ParsedSymbolType::SOURCE_FILE;
|
||||
so_symbol.raw = &symbol;
|
||||
break;
|
||||
}
|
||||
case mdebug::STAB:
|
||||
case mdebug::N_OPT:
|
||||
case mdebug::N_BINCL:
|
||||
case mdebug::N_EINCL: {
|
||||
break;
|
||||
}
|
||||
case mdebug::N_FNAME:
|
||||
case mdebug::N_MAIN:
|
||||
case mdebug::N_PC:
|
||||
case mdebug::N_NSYMS:
|
||||
case mdebug::N_NOMAP:
|
||||
case mdebug::N_OBJ:
|
||||
case mdebug::N_M2C:
|
||||
case mdebug::N_SLINE:
|
||||
case mdebug::N_DSLINE:
|
||||
case mdebug::N_BSLINE:
|
||||
case mdebug::N_EFD:
|
||||
case mdebug::N_EHDECL:
|
||||
case mdebug::N_CATCH:
|
||||
case mdebug::N_SSYM:
|
||||
case mdebug::N_ENTRY:
|
||||
case mdebug::N_EXCL:
|
||||
case mdebug::N_SCOPE:
|
||||
case mdebug::N_BCOMM:
|
||||
case mdebug::N_ECOMM:
|
||||
case mdebug::N_ECOML:
|
||||
case mdebug::N_NBTEXT:
|
||||
case mdebug::N_NBDATA:
|
||||
case mdebug::N_NBBSS:
|
||||
case mdebug::N_NBSTS:
|
||||
case mdebug::N_NBLCS:
|
||||
case mdebug::N_LENG: {
|
||||
CCC_WARN("Unhandled N_%s symbol: %s", mdebug::stabs_code_to_string(symbol.code()), symbol.string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ParsedSymbol& non_stabs_symbol = output.emplace_back();
|
||||
non_stabs_symbol.type = ParsedSymbolType::NON_STABS;
|
||||
non_stabs_symbol.raw = &symbol;
|
||||
}
|
||||
}
|
||||
|
||||
mark_duplicate_symbols(output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static void mark_duplicate_symbols(std::vector<ParsedSymbol>& symbols)
|
||||
{
|
||||
std::map<StabsTypeNumber, size_t> stabs_type_number_to_symbol;
|
||||
for(size_t i = 0; i < symbols.size(); i++) {
|
||||
ParsedSymbol& symbol = symbols[i];
|
||||
if(symbol.type == ParsedSymbolType::NAME_COLON_TYPE) {
|
||||
StabsType& type = *symbol.name_colon_type.type;
|
||||
if(type.type_number.valid() && type.descriptor.has_value()) {
|
||||
stabs_type_number_to_symbol.emplace(type.type_number, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(ParsedSymbol& symbol : symbols) {
|
||||
symbol.is_typedef =
|
||||
symbol.type == ParsedSymbolType::NAME_COLON_TYPE &&
|
||||
symbol.name_colon_type.descriptor == StabsSymbolDescriptor::TYPE_NAME &&
|
||||
symbol.name_colon_type.type->descriptor != StabsTypeDescriptor::ENUM;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < symbols.size(); i++) {
|
||||
ParsedSymbol& symbol = symbols[i];
|
||||
if(symbol.type != ParsedSymbolType::NAME_COLON_TYPE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_type =
|
||||
symbol.name_colon_type.descriptor == StabsSymbolDescriptor::TYPE_NAME ||
|
||||
symbol.name_colon_type.descriptor == StabsSymbolDescriptor::ENUM_STRUCT_OR_TYPE_TAG;
|
||||
if(!is_type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
StabsType& type = *symbol.name_colon_type.type;
|
||||
|
||||
if(!type.descriptor.has_value()) {
|
||||
auto referenced_index = stabs_type_number_to_symbol.find(type.type_number);
|
||||
if(referenced_index != stabs_type_number_to_symbol.end()) {
|
||||
ParsedSymbol& referenced = symbols[referenced_index->second];
|
||||
if(referenced.name_colon_type.name == symbol.name_colon_type.name) {
|
||||
// symbol: "Struct:T(1,1)=s1;"
|
||||
// referenced: "Struct:t(1,1)"
|
||||
symbol.duplicate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(type.descriptor.has_value() && type.descriptor == StabsTypeDescriptor::TYPE_REFERENCE) {
|
||||
auto referenced_index = stabs_type_number_to_symbol.find(type.as<StabsTypeReferenceType>().type->type_number);
|
||||
if(referenced_index != stabs_type_number_to_symbol.end() && referenced_index->second != i) {
|
||||
ParsedSymbol& referenced = symbols[referenced_index->second];
|
||||
|
||||
if(referenced.name_colon_type.name == " ") {
|
||||
// referenced: " :T(1,1)=e;"
|
||||
// symbol: "ErraticEnum:t(1,2)=(1,1)"
|
||||
referenced.name_colon_type.name = symbol.name_colon_type.name;
|
||||
referenced.is_typedef = true;
|
||||
symbol.duplicate = true;
|
||||
}
|
||||
|
||||
if(referenced.name_colon_type.name == symbol.name_colon_type.name) {
|
||||
// referenced: "NamedTypedefedStruct:T(1,1)=s1;"
|
||||
// symbol: "NamedTypedefedStruct:t(1,2)=(1,1)"
|
||||
referenced.is_typedef = true;
|
||||
symbol.duplicate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
32
3rdparty/ccc/src/ccc/mdebug_symbols.h
vendored
Normal file
32
3rdparty/ccc/src/ccc/mdebug_symbols.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util.h"
|
||||
#include "stabs.h"
|
||||
#include "mdebug_section.h"
|
||||
|
||||
namespace ccc::mdebug {
|
||||
|
||||
enum class ParsedSymbolType {
|
||||
NAME_COLON_TYPE,
|
||||
SOURCE_FILE,
|
||||
SUB_SOURCE_FILE,
|
||||
LBRAC,
|
||||
RBRAC,
|
||||
FUNCTION_END,
|
||||
NON_STABS
|
||||
};
|
||||
|
||||
struct ParsedSymbol {
|
||||
ParsedSymbolType type;
|
||||
const mdebug::Symbol* raw;
|
||||
StabsSymbol name_colon_type;
|
||||
bool duplicate = false;
|
||||
bool is_typedef = false;
|
||||
};
|
||||
|
||||
Result<std::vector<ParsedSymbol>> parse_symbols(const std::vector<mdebug::Symbol>& input, u32& importer_flags);
|
||||
|
||||
}
|
||||
193
3rdparty/ccc/src/ccc/sndll.cpp
vendored
Normal file
193
3rdparty/ccc/src/ccc/sndll.cpp
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "sndll.h"
|
||||
|
||||
#include "importer_flags.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
CCC_PACKED_STRUCT(SNDLLHeaderCommon,
|
||||
/* 0x00 */ u32 magic;
|
||||
/* 0x04 */ u32 relocations;
|
||||
/* 0x08 */ u32 relocation_count;
|
||||
/* 0x0c */ u32 symbols;
|
||||
/* 0x10 */ u32 symbol_count;
|
||||
/* 0x14 */ u32 elf_path;
|
||||
/* 0x18 */ u32 load_func;
|
||||
/* 0x1c */ u32 unload_func;
|
||||
/* 0x20 */ u32 unknown_20;
|
||||
/* 0x24 */ u32 unknown_24;
|
||||
/* 0x28 */ u32 unknown_28;
|
||||
/* 0x2c */ u32 file_size;
|
||||
/* 0x30 */ u32 unknown_30;
|
||||
)
|
||||
|
||||
CCC_PACKED_STRUCT(SNDLLHeaderV1,
|
||||
/* 0x00 */ SNDLLHeaderCommon common;
|
||||
)
|
||||
|
||||
CCC_PACKED_STRUCT(SNDLLHeaderV2,
|
||||
/* 0x00 */ SNDLLHeaderCommon common;
|
||||
/* 0x34 */ u32 unknown_34;
|
||||
/* 0x38 */ u32 unknown_38;
|
||||
)
|
||||
|
||||
CCC_PACKED_STRUCT(SNDLLRelocation,
|
||||
/* 0x0 */ u32 unknown_0;
|
||||
/* 0x4 */ u32 unknown_4;
|
||||
/* 0x8 */ u32 unknown_8;
|
||||
)
|
||||
|
||||
CCC_PACKED_STRUCT(SNDLLSymbolHeader,
|
||||
/* 0x0 */ u32 string;
|
||||
/* 0x4 */ u32 value;
|
||||
/* 0x8 */ u8 unknown_8;
|
||||
/* 0x9 */ u8 unknown_9;
|
||||
/* 0xa */ SNDLLSymbolType type;
|
||||
/* 0xb */ u8 processed;
|
||||
)
|
||||
|
||||
static Result<SNDLLFile> parse_sndll_common(
|
||||
std::span<const u8> image, Address address, SNDLLType type, const SNDLLHeaderCommon& common, SNDLLVersion version);
|
||||
static const char* sndll_symbol_type_to_string(SNDLLSymbolType type);
|
||||
|
||||
Result<SNDLLFile> parse_sndll_file(std::span<const u8> image, Address address, SNDLLType type)
|
||||
{
|
||||
std::optional<u32> magic = copy_unaligned<u32>(image, 0);
|
||||
CCC_CHECK(magic.has_value(), "Failed to read SNDLL header.");
|
||||
CCC_CHECK((*magic & 0xffffff) == CCC_FOURCC("SNR\00"), "Not a SNDLL %s.", address.valid() ? "section" : "file");
|
||||
|
||||
char version = *magic >> 24;
|
||||
switch(version) {
|
||||
case '1': {
|
||||
const SNDLLHeaderV1* header = get_unaligned<SNDLLHeaderV1>(image, 0);
|
||||
CCC_CHECK(header, "File too small to contain SNDLL V1 header.");
|
||||
return parse_sndll_common(image, address, type, header->common, SNDLL_V1);
|
||||
}
|
||||
case '2': {
|
||||
const SNDLLHeaderV2* header = get_unaligned<SNDLLHeaderV2>(image, 0);
|
||||
CCC_CHECK(header, "File too small to contain SNDLL V2 header.");
|
||||
return parse_sndll_common(image, address, type, header->common, SNDLL_V2);
|
||||
}
|
||||
}
|
||||
|
||||
return CCC_FAILURE("Unknown SNDLL version '%c'.", version);
|
||||
}
|
||||
|
||||
static Result<SNDLLFile> parse_sndll_common(
|
||||
std::span<const u8> image, Address address, SNDLLType type, const SNDLLHeaderCommon& common, SNDLLVersion version)
|
||||
{
|
||||
SNDLLFile sndll;
|
||||
|
||||
sndll.address = address;
|
||||
sndll.type = type;
|
||||
sndll.version = version;
|
||||
|
||||
if(common.elf_path) {
|
||||
std::optional<std::string_view> elf_path = get_string(image, common.elf_path);
|
||||
CCC_CHECK(elf_path.has_value(), "SNDLL header has invalid ELF path field.");
|
||||
sndll.elf_path = *elf_path;
|
||||
}
|
||||
|
||||
CCC_CHECK(common.symbol_count < (32 * 1024 * 1024) / sizeof(SNDLLSymbol), "SNDLL symbol count is too high.");
|
||||
sndll.symbols.reserve(common.symbol_count);
|
||||
|
||||
for(u32 i = 0; i < common.symbol_count; i++) {
|
||||
u32 symbol_offset = common.symbols - address.get_or_zero() + i * sizeof(SNDLLSymbolHeader);
|
||||
const SNDLLSymbolHeader* symbol_header = get_unaligned<SNDLLSymbolHeader>(image, symbol_offset);
|
||||
CCC_CHECK(symbol_header, "SNDLL symbol out of range.");
|
||||
|
||||
std::optional<std::string_view> string;
|
||||
if(symbol_header->string) {
|
||||
string = get_string(image, symbol_header->string - address.get_or_zero());
|
||||
}
|
||||
|
||||
SNDLLSymbol& symbol = sndll.symbols.emplace_back();
|
||||
symbol.type = symbol_header->type;
|
||||
symbol.value = symbol_header->value;
|
||||
if(string.has_value()) {
|
||||
symbol.string = *string;
|
||||
}
|
||||
}
|
||||
|
||||
return sndll;
|
||||
}
|
||||
|
||||
Result<void> import_sndll_symbols(
|
||||
SymbolDatabase& database,
|
||||
const SNDLLFile& sndll,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler)
|
||||
{
|
||||
for(const SNDLLSymbol& symbol : sndll.symbols) {
|
||||
if(symbol.value == 0 || symbol.string.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
u32 address = symbol.value;
|
||||
if(symbol.type != SNDLL_ABSOLUTE && sndll.type == SNDLLType::DYNAMIC_LIBRARY) {
|
||||
address += sndll.address.get_or_zero();
|
||||
}
|
||||
|
||||
if(!(importer_flags & DONT_DEDUPLICATE_SYMBOLS)) {
|
||||
if(database.functions.first_handle_from_starting_address(address).valid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(database.global_variables.first_handle_from_starting_address(address).valid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(database.local_variables.first_handle_from_starting_address(address).valid()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const Section* section = database.sections.symbol_overlapping_address(address);
|
||||
if(section) {
|
||||
if(section->contains_code()) {
|
||||
Result<Function*> function = database.functions.create_symbol(
|
||||
symbol.string, group.source, group.module_symbol, address, importer_flags, demangler);
|
||||
CCC_RETURN_IF_ERROR(function);
|
||||
continue;
|
||||
} else if(section->contains_data()) {
|
||||
Result<GlobalVariable*> global_variable = database.global_variables.create_symbol(
|
||||
symbol.string, group.source, group.module_symbol, address, importer_flags, demangler);
|
||||
CCC_RETURN_IF_ERROR(global_variable);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Result<Label*> label = database.labels.create_symbol(
|
||||
symbol.string, group.source, group.module_symbol, address, importer_flags, demangler);
|
||||
CCC_RETURN_IF_ERROR(label);
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
void print_sndll_symbols(FILE* out, const SNDLLFile& sndll)
|
||||
{
|
||||
fprintf(out, "SNDLL SYMBOLS:\n");
|
||||
for(const SNDLLSymbol& symbol : sndll.symbols) {
|
||||
const char* type = sndll_symbol_type_to_string(symbol.type);
|
||||
const char* string = !symbol.string.empty() ? symbol.string.c_str() : "(no string)";
|
||||
fprintf(out, "%8s %08x %s\n", type, symbol.value, string);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* sndll_symbol_type_to_string(SNDLLSymbolType type)
|
||||
{
|
||||
switch(type) {
|
||||
case SNDLL_NIL: return "NIL";
|
||||
case SNDLL_EXTERNAL: return "EXTERNAL";
|
||||
case SNDLL_RELATIVE: return "RELATIVE";
|
||||
case SNDLL_WEAK: return "WEAK";
|
||||
case SNDLL_ABSOLUTE: return "ABSOLUTE";
|
||||
}
|
||||
return "invalid";
|
||||
}
|
||||
|
||||
}
|
||||
55
3rdparty/ccc/src/ccc/sndll.h
vendored
Normal file
55
3rdparty/ccc/src/ccc/sndll.h
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "symbol_database.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
enum class SNDLLType {
|
||||
SNDATA_SECTION,
|
||||
DYNAMIC_LIBRARY
|
||||
};
|
||||
|
||||
enum SNDLLVersion {
|
||||
SNDLL_V1,
|
||||
SNDLL_V2
|
||||
};
|
||||
|
||||
enum SNDLLSymbolType : u8 {
|
||||
SNDLL_NIL = 0, // I think this is just so that the first real symbol has an index of 1.
|
||||
SNDLL_EXTERNAL = 1, // Symbol with an empty value, to be filled in from another module.
|
||||
SNDLL_RELATIVE = 2, // Global symbol, value is relative to the start of the SNDLL file.
|
||||
SNDLL_WEAK = 3, // Weak symbol, value is relative to the start of the SNDLL file.
|
||||
SNDLL_ABSOLUTE = 4 // Global symbol, value is an absolute address.
|
||||
};
|
||||
|
||||
struct SNDLLSymbol {
|
||||
SNDLLSymbolType type = SNDLL_NIL;
|
||||
u32 value = 0;
|
||||
std::string string;
|
||||
};
|
||||
|
||||
struct SNDLLFile {
|
||||
Address address;
|
||||
SNDLLType type;
|
||||
SNDLLVersion version;
|
||||
std::string elf_path;
|
||||
std::vector<SNDLLSymbol> symbols;
|
||||
};
|
||||
|
||||
// If a valid address is passed, the pointers in the header will be treated as
|
||||
// addresses, otherwise they will be treated as file offsets.
|
||||
Result<SNDLLFile> parse_sndll_file(std::span<const u8> image, Address address, SNDLLType type);
|
||||
|
||||
Result<void> import_sndll_symbols(
|
||||
SymbolDatabase& database,
|
||||
const SNDLLFile& sndll,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler);
|
||||
|
||||
void print_sndll_symbols(FILE* out, const SNDLLFile& sndll);
|
||||
|
||||
}
|
||||
835
3rdparty/ccc/src/ccc/stabs.cpp
vendored
Normal file
835
3rdparty/ccc/src/ccc/stabs.cpp
vendored
Normal file
@@ -0,0 +1,835 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "stabs.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
#define STABS_DEBUG(...) //__VA_ARGS__
|
||||
#define STABS_DEBUG_PRINTF(...) STABS_DEBUG(printf(__VA_ARGS__);)
|
||||
|
||||
static bool validate_symbol_descriptor(StabsSymbolDescriptor descriptor);
|
||||
static Result<std::unique_ptr<StabsType>> parse_stabs_type(const char*& input);
|
||||
static Result<std::vector<StabsStructOrUnionType::Field>> parse_field_list(const char*& input);
|
||||
static Result<std::vector<StabsStructOrUnionType::MemberFunctionSet>> parse_member_functions(const char*& input);
|
||||
static Result<StabsStructOrUnionType::Visibility> parse_visibility_character(const char*& input);
|
||||
STABS_DEBUG(static void print_field(const StabsStructOrUnionType::Field& field);)
|
||||
|
||||
const char* STAB_TRUNCATED_ERROR_MESSAGE =
|
||||
"STABS symbol truncated. This was probably caused by a GCC bug. "
|
||||
"Other symbols from the same translation unit may also be invalid.";
|
||||
|
||||
Result<StabsSymbol> parse_stabs_symbol(const char*& input)
|
||||
{
|
||||
STABS_DEBUG_PRINTF("PARSING %s\n", input);
|
||||
|
||||
StabsSymbol symbol;
|
||||
|
||||
Result<std::string> name = parse_dodgy_stabs_identifier(input, ':');
|
||||
CCC_RETURN_IF_ERROR(name);
|
||||
|
||||
symbol.name = *name;
|
||||
|
||||
CCC_EXPECT_CHAR(input, ':', "identifier");
|
||||
CCC_CHECK(*input != '\0', "Unexpected end of input.");
|
||||
if((*input >= '0' && *input <= '9') || *input == '(') {
|
||||
symbol.descriptor = StabsSymbolDescriptor::LOCAL_VARIABLE;
|
||||
} else {
|
||||
char symbol_descriptor = *(input++);
|
||||
CCC_CHECK(symbol_descriptor != '\0', "Failed to parse symbol descriptor.");
|
||||
symbol.descriptor = (StabsSymbolDescriptor) symbol_descriptor;
|
||||
}
|
||||
CCC_CHECK(validate_symbol_descriptor(symbol.descriptor),
|
||||
"Invalid symbol descriptor '%c'.",
|
||||
(char) symbol.descriptor);
|
||||
CCC_CHECK(*input != '\0', "Unexpected end of input.");
|
||||
if(*input == 't') {
|
||||
input++;
|
||||
}
|
||||
|
||||
auto type = parse_top_level_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(type);
|
||||
|
||||
// Handle nested functions.
|
||||
bool is_function =
|
||||
symbol.descriptor == StabsSymbolDescriptor::LOCAL_FUNCTION ||
|
||||
symbol.descriptor == StabsSymbolDescriptor::GLOBAL_FUNCTION;
|
||||
if(is_function && input[0] == ',') {
|
||||
input++;
|
||||
while(*input != ',' && *input != '\0') input++; // enclosing function
|
||||
CCC_EXPECT_CHAR(input, ',', "nested function suffix");
|
||||
while(*input != ',' && *input != '\0') input++; // function
|
||||
}
|
||||
|
||||
symbol.type = std::move(*type);
|
||||
|
||||
// Make sure that variable names aren't used as type names e.g. the STABS
|
||||
// symbol "somevar:P123=*456" may be referenced by the type number 123, but
|
||||
// the type name is not "somevar".
|
||||
bool is_type = symbol.descriptor == StabsSymbolDescriptor::TYPE_NAME
|
||||
|| symbol.descriptor == StabsSymbolDescriptor::ENUM_STRUCT_OR_TYPE_TAG;
|
||||
if(is_type) {
|
||||
symbol.type->name = symbol.name;
|
||||
}
|
||||
|
||||
symbol.type->is_typedef = symbol.descriptor == StabsSymbolDescriptor::TYPE_NAME;
|
||||
symbol.type->is_root = true;
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
static bool validate_symbol_descriptor(StabsSymbolDescriptor descriptor)
|
||||
{
|
||||
bool valid;
|
||||
switch(descriptor) {
|
||||
case StabsSymbolDescriptor::LOCAL_VARIABLE:
|
||||
case StabsSymbolDescriptor::REFERENCE_PARAMETER_A:
|
||||
case StabsSymbolDescriptor::LOCAL_FUNCTION:
|
||||
case StabsSymbolDescriptor::GLOBAL_FUNCTION:
|
||||
case StabsSymbolDescriptor::GLOBAL_VARIABLE:
|
||||
case StabsSymbolDescriptor::REGISTER_PARAMETER:
|
||||
case StabsSymbolDescriptor::VALUE_PARAMETER:
|
||||
case StabsSymbolDescriptor::REGISTER_VARIABLE:
|
||||
case StabsSymbolDescriptor::STATIC_GLOBAL_VARIABLE:
|
||||
case StabsSymbolDescriptor::TYPE_NAME:
|
||||
case StabsSymbolDescriptor::ENUM_STRUCT_OR_TYPE_TAG:
|
||||
case StabsSymbolDescriptor::STATIC_LOCAL_VARIABLE:
|
||||
case StabsSymbolDescriptor::REFERENCE_PARAMETER_V:
|
||||
valid = true;
|
||||
break;
|
||||
default:
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
Result<std::unique_ptr<StabsType>> parse_top_level_stabs_type(const char*& input)
|
||||
{
|
||||
Result<std::unique_ptr<StabsType>> type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(type);
|
||||
|
||||
// Handle first base class suffixes.
|
||||
if((*type)->descriptor == StabsTypeDescriptor::STRUCT && input[0] == '~' && input[1] == '%') {
|
||||
input += 2;
|
||||
|
||||
Result<std::unique_ptr<StabsType>> first_base_class = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(first_base_class);
|
||||
(*type)->as<StabsStructType>().first_base_class = std::move(*first_base_class);
|
||||
|
||||
CCC_EXPECT_CHAR(input, ';', "first base class suffix");
|
||||
}
|
||||
|
||||
// Handle extra live range information.
|
||||
if(input[0] == ';' && input[1] == 'l') {
|
||||
input += 2;
|
||||
CCC_EXPECT_CHAR(input, '(', "live range suffix");
|
||||
CCC_EXPECT_CHAR(input, '#', "live range suffix");
|
||||
std::optional<s32> start = parse_number_s32(input);
|
||||
CCC_CHECK(start.has_value(), "Failed to parse live range suffix.");
|
||||
CCC_EXPECT_CHAR(input, ',', "live range suffix");
|
||||
CCC_EXPECT_CHAR(input, '#', "live range suffix");
|
||||
std::optional<s32> end = parse_number_s32(input);
|
||||
CCC_CHECK(end.has_value(), "Failed to parse live range suffix.");
|
||||
CCC_EXPECT_CHAR(input, ')', "live range suffix");
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static Result<std::unique_ptr<StabsType>> parse_stabs_type(const char*& input)
|
||||
{
|
||||
StabsTypeNumber type_number;
|
||||
|
||||
CCC_CHECK(*input != '\0', "Unexpected end of input.");
|
||||
|
||||
if(*input == '(') {
|
||||
// This file has type numbers made up of two pieces: an include file
|
||||
// index and a type number.
|
||||
|
||||
input++;
|
||||
|
||||
std::optional<s32> file_index = parse_number_s32(input);
|
||||
CCC_CHECK(file_index.has_value(), "Failed to parse type number (file index).");
|
||||
|
||||
CCC_EXPECT_CHAR(input, ',', "type number");
|
||||
|
||||
std::optional<s32> type_index = parse_number_s32(input);
|
||||
CCC_CHECK(type_index.has_value(), "Failed to parse type number (type index).");
|
||||
|
||||
CCC_EXPECT_CHAR(input, ')', "type number");
|
||||
|
||||
type_number.file = *file_index;
|
||||
type_number.type = *type_index;
|
||||
|
||||
if(*input != '=') {
|
||||
return std::make_unique<StabsType>(type_number);
|
||||
}
|
||||
input++;
|
||||
} else if(*input >= '0' && *input <= '9') {
|
||||
// This file has type numbers which are just a single number. This is
|
||||
// the more common case for games.
|
||||
|
||||
std::optional<s32> type_index = parse_number_s32(input);
|
||||
CCC_CHECK(type_index.has_value(), "Failed to parse type number.");
|
||||
type_number.type = *type_index;
|
||||
|
||||
if(*input != '=') {
|
||||
return std::make_unique<StabsType>(type_number);
|
||||
}
|
||||
input++;
|
||||
}
|
||||
|
||||
CCC_CHECK(*input != '\0', "Unexpected end of input.");
|
||||
|
||||
StabsTypeDescriptor descriptor;
|
||||
if((*input >= '0' && *input <= '9') || *input == '(') {
|
||||
descriptor = StabsTypeDescriptor::TYPE_REFERENCE;
|
||||
} else {
|
||||
char descriptor_char = *(input++);
|
||||
CCC_CHECK(descriptor_char != '\0', "Failed to parse type descriptor.");
|
||||
descriptor = (StabsTypeDescriptor) descriptor_char;
|
||||
}
|
||||
|
||||
std::unique_ptr<StabsType> out_type;
|
||||
|
||||
switch(descriptor) {
|
||||
case StabsTypeDescriptor::TYPE_REFERENCE: { // 0..9
|
||||
auto type_reference = std::make_unique<StabsTypeReferenceType>(type_number);
|
||||
|
||||
auto type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(type);
|
||||
type_reference->type = std::move(*type);
|
||||
|
||||
out_type = std::move(type_reference);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::ARRAY: { // a
|
||||
auto array = std::make_unique<StabsArrayType>(type_number);
|
||||
|
||||
auto index_type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(index_type);
|
||||
array->index_type = std::move(*index_type);
|
||||
|
||||
auto element_type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(element_type);
|
||||
array->element_type = std::move(*element_type);
|
||||
|
||||
out_type = std::move(array);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::ENUM: { // e
|
||||
auto enum_type = std::make_unique<StabsEnumType>(type_number);
|
||||
STABS_DEBUG_PRINTF("enum {\n");
|
||||
while(*input != ';') {
|
||||
std::optional<std::string> name = parse_stabs_identifier(input, ':');
|
||||
CCC_CHECK(name.has_value(), "Failed to parse enum field name.");
|
||||
|
||||
CCC_EXPECT_CHAR(input, ':', "enum");
|
||||
|
||||
std::optional<s32> value = parse_number_s32(input);
|
||||
CCC_CHECK(value.has_value(), "Failed to parse enum value.");
|
||||
|
||||
enum_type->fields.emplace_back(*value, std::move(*name));
|
||||
|
||||
CCC_EXPECT_CHAR(input, ',', "enum");
|
||||
}
|
||||
input++;
|
||||
STABS_DEBUG_PRINTF("}\n");
|
||||
|
||||
out_type = std::move(enum_type);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::FUNCTION: { // f
|
||||
auto function = std::make_unique<StabsFunctionType>(type_number);
|
||||
|
||||
auto return_type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(return_type);
|
||||
function->return_type = std::move(*return_type);
|
||||
|
||||
out_type = std::move(function);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::VOLATILE_QUALIFIER: { // B
|
||||
auto volatile_qualifier = std::make_unique<StabsVolatileQualifierType>(type_number);
|
||||
|
||||
auto type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(type);
|
||||
volatile_qualifier->type = std::move(*type);
|
||||
|
||||
out_type = std::move(volatile_qualifier);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::CONST_QUALIFIER: { // k
|
||||
auto const_qualifier = std::make_unique<StabsConstQualifierType>(type_number);
|
||||
|
||||
auto type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(type);
|
||||
const_qualifier->type = std::move(*type);
|
||||
|
||||
out_type = std::move(const_qualifier);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::RANGE: { // r
|
||||
auto range = std::make_unique<StabsRangeType>(type_number);
|
||||
|
||||
auto type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(type);
|
||||
range->type = std::move(*type);
|
||||
|
||||
CCC_EXPECT_CHAR(input, ';', "range type descriptor");
|
||||
|
||||
std::optional<std::string> low = parse_stabs_identifier(input, ';');
|
||||
CCC_CHECK(low.has_value(), "Failed to parse low part of range.");
|
||||
CCC_EXPECT_CHAR(input, ';', "low range value");
|
||||
|
||||
std::optional<std::string> high = parse_stabs_identifier(input, ';');
|
||||
CCC_CHECK(high.has_value(), "Failed to parse high part of range.");
|
||||
CCC_EXPECT_CHAR(input, ';', "high range value");
|
||||
|
||||
range->low = std::move(*low);
|
||||
range->high = std::move(*high);
|
||||
|
||||
out_type = std::move(range);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::STRUCT: { // s
|
||||
auto struct_type = std::make_unique<StabsStructType>(type_number);
|
||||
STABS_DEBUG_PRINTF("struct {\n");
|
||||
|
||||
std::optional<s64> struct_size = parse_number_s64(input);
|
||||
CCC_CHECK(struct_size.has_value(), "Failed to parse struct size.");
|
||||
struct_type->size = *struct_size;
|
||||
|
||||
if(*input == '!') {
|
||||
input++;
|
||||
std::optional<s32> base_class_count = parse_number_s32(input);
|
||||
CCC_CHECK(base_class_count.has_value(), "Failed to parse base class count.");
|
||||
|
||||
CCC_EXPECT_CHAR(input, ',', "base class section");
|
||||
|
||||
for(s64 i = 0; i < *base_class_count; i++) {
|
||||
StabsStructOrUnionType::BaseClass base_class;
|
||||
|
||||
char is_virtual = *(input++);
|
||||
switch(is_virtual) {
|
||||
case '0': base_class.is_virtual = false; break;
|
||||
case '1': base_class.is_virtual = true; break;
|
||||
default: return CCC_FAILURE("Failed to parse base class (virtual character).");
|
||||
}
|
||||
|
||||
Result<StabsStructOrUnionType::Visibility> visibility = parse_visibility_character(input);
|
||||
CCC_RETURN_IF_ERROR(visibility);
|
||||
base_class.visibility = *visibility;
|
||||
|
||||
std::optional<s32> offset = parse_number_s32(input);
|
||||
CCC_CHECK(offset.has_value(), "Failed to parse base class offset.");
|
||||
base_class.offset = (s32) *offset;
|
||||
|
||||
CCC_EXPECT_CHAR(input, ',', "base class section");
|
||||
|
||||
auto base_class_type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(base_class_type);
|
||||
base_class.type = std::move(*base_class_type);
|
||||
|
||||
CCC_EXPECT_CHAR(input, ';', "base class section");
|
||||
struct_type->base_classes.emplace_back(std::move(base_class));
|
||||
}
|
||||
}
|
||||
|
||||
auto fields = parse_field_list(input);
|
||||
CCC_RETURN_IF_ERROR(fields);
|
||||
struct_type->fields = std::move(*fields);
|
||||
|
||||
auto member_functions = parse_member_functions(input);
|
||||
CCC_RETURN_IF_ERROR(member_functions);
|
||||
struct_type->member_functions = std::move(*member_functions);
|
||||
|
||||
STABS_DEBUG_PRINTF("}\n");
|
||||
|
||||
out_type = std::move(struct_type);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::UNION: { // u
|
||||
auto union_type = std::make_unique<StabsUnionType>(type_number);
|
||||
STABS_DEBUG_PRINTF("union {\n");
|
||||
|
||||
std::optional<s64> union_size = parse_number_s64(input);
|
||||
CCC_CHECK(union_size.has_value(), "Failed to parse struct size.");
|
||||
union_type->size = *union_size;
|
||||
|
||||
auto fields = parse_field_list(input);
|
||||
CCC_RETURN_IF_ERROR(fields);
|
||||
union_type->fields = std::move(*fields);
|
||||
|
||||
auto member_functions = parse_member_functions(input);
|
||||
CCC_RETURN_IF_ERROR(member_functions);
|
||||
union_type->member_functions = std::move(*member_functions);
|
||||
|
||||
STABS_DEBUG_PRINTF("}\n");
|
||||
|
||||
out_type = std::move(union_type);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::CROSS_REFERENCE: { // x
|
||||
auto cross_reference = std::make_unique<StabsCrossReferenceType>(type_number);
|
||||
|
||||
char cross_reference_type = *(input++);
|
||||
CCC_CHECK(cross_reference_type != '\0', "Failed to parse cross reference type.");
|
||||
|
||||
switch(cross_reference_type) {
|
||||
case 'e': cross_reference->type = ast::ForwardDeclaredType::ENUM; break;
|
||||
case 's': cross_reference->type = ast::ForwardDeclaredType::STRUCT; break;
|
||||
case 'u': cross_reference->type = ast::ForwardDeclaredType::UNION; break;
|
||||
default:
|
||||
return CCC_FAILURE("Invalid cross reference type '%c'.", cross_reference->type);
|
||||
}
|
||||
|
||||
Result<std::string> identifier = parse_dodgy_stabs_identifier(input, ':');
|
||||
CCC_RETURN_IF_ERROR(identifier);
|
||||
cross_reference->identifier = std::move(*identifier);
|
||||
|
||||
cross_reference->name = cross_reference->identifier;
|
||||
CCC_EXPECT_CHAR(input, ':', "cross reference");
|
||||
|
||||
out_type = std::move(cross_reference);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::FLOATING_POINT_BUILTIN: { // R
|
||||
auto fp_builtin = std::make_unique<StabsFloatingPointBuiltInType>(type_number);
|
||||
|
||||
std::optional<s32> fpclass = parse_number_s32(input);
|
||||
CCC_CHECK(fpclass.has_value(), "Failed to parse floating point built-in class.");
|
||||
fp_builtin->fpclass = *fpclass;
|
||||
|
||||
CCC_EXPECT_CHAR(input, ';', "floating point builtin");
|
||||
|
||||
std::optional<s32> bytes = parse_number_s32(input);
|
||||
CCC_CHECK(bytes.has_value(), "Failed to parse floating point built-in.");
|
||||
fp_builtin->bytes = *bytes;
|
||||
|
||||
CCC_EXPECT_CHAR(input, ';', "floating point builtin");
|
||||
|
||||
std::optional<s32> value = parse_number_s32(input);
|
||||
CCC_CHECK(value.has_value(), "Failed to parse floating point built-in.");
|
||||
|
||||
CCC_EXPECT_CHAR(input, ';', "floating point builtin");
|
||||
|
||||
out_type = std::move(fp_builtin);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::METHOD: { // #
|
||||
auto method = std::make_unique<StabsMethodType>(type_number);
|
||||
|
||||
if(*input == '#') {
|
||||
input++;
|
||||
|
||||
auto return_type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(return_type);
|
||||
method->return_type = std::move(*return_type);
|
||||
|
||||
if(*input == ';') {
|
||||
input++;
|
||||
}
|
||||
} else {
|
||||
auto class_type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(class_type);
|
||||
method->class_type = std::move(*class_type);
|
||||
|
||||
CCC_EXPECT_CHAR(input, ',', "method");
|
||||
|
||||
auto return_type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(return_type);
|
||||
method->return_type = std::move(*return_type);
|
||||
|
||||
while(*input != '\0') {
|
||||
if(*input == ';') {
|
||||
input++;
|
||||
break;
|
||||
}
|
||||
|
||||
CCC_EXPECT_CHAR(input, ',', "method");
|
||||
|
||||
auto parameter_type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(parameter_type);
|
||||
method->parameter_types.emplace_back(std::move(*parameter_type));
|
||||
}
|
||||
}
|
||||
|
||||
out_type = std::move(method);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::REFERENCE: { // &
|
||||
auto reference = std::make_unique<StabsReferenceType>(type_number);
|
||||
|
||||
auto value_type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(value_type);
|
||||
reference->value_type = std::move(*value_type);
|
||||
|
||||
out_type = std::move(reference);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::POINTER: { // *
|
||||
auto pointer = std::make_unique<StabsPointerType>(type_number);
|
||||
|
||||
auto value_type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(value_type);
|
||||
pointer->value_type = std::move(*value_type);
|
||||
|
||||
out_type = std::move(pointer);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::TYPE_ATTRIBUTE: { // @
|
||||
if((*input >= '0' && *input <= '9') || *input == '(') {
|
||||
auto member_pointer = std::make_unique<StabsPointerToDataMemberType>(type_number);
|
||||
|
||||
auto class_type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(class_type);
|
||||
member_pointer->class_type = std::move(*class_type);
|
||||
|
||||
CCC_EXPECT_CHAR(input, ',', "pointer to non-static data member");
|
||||
|
||||
auto member_type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(member_type);
|
||||
member_pointer->member_type = std::move(*member_type);
|
||||
|
||||
out_type = std::move(member_pointer);
|
||||
} else {
|
||||
auto type_attribute = std::make_unique<StabsSizeTypeAttributeType>(type_number);
|
||||
CCC_CHECK(*input == 's', "Weird value following '@' type descriptor.");
|
||||
input++;
|
||||
|
||||
std::optional<s64> size_bits = parse_number_s64(input);
|
||||
CCC_CHECK(size_bits.has_value(), "Failed to parse type attribute.")
|
||||
type_attribute->size_bits = *size_bits;
|
||||
CCC_EXPECT_CHAR(input, ';', "type attribute");
|
||||
|
||||
auto type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(type);
|
||||
type_attribute->type = std::move(*type);
|
||||
|
||||
out_type = std::move(type_attribute);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::BUILTIN: { // -
|
||||
auto built_in = std::make_unique<StabsBuiltInType>(type_number);
|
||||
|
||||
std::optional<s64> type_id = parse_number_s64(input);
|
||||
CCC_CHECK(type_id.has_value(), "Failed to parse built-in.");
|
||||
built_in->type_id = *type_id;
|
||||
|
||||
CCC_EXPECT_CHAR(input, ';', "builtin");
|
||||
|
||||
out_type = std::move(built_in);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return CCC_FAILURE(
|
||||
"Invalid type descriptor '%c' (%02x).",
|
||||
(u32) descriptor, (u32) descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
return out_type;
|
||||
}
|
||||
|
||||
static Result<std::vector<StabsStructOrUnionType::Field>> parse_field_list(const char*& input)
|
||||
{
|
||||
std::vector<StabsStructOrUnionType::Field> fields;
|
||||
|
||||
while(*input != '\0') {
|
||||
if(*input == ';') {
|
||||
input++;
|
||||
break;
|
||||
}
|
||||
|
||||
const char* before_field = input;
|
||||
StabsStructOrUnionType::Field field;
|
||||
|
||||
Result<std::string> name = parse_dodgy_stabs_identifier(input, ':');
|
||||
CCC_RETURN_IF_ERROR(name);
|
||||
field.name = std::move(*name);
|
||||
|
||||
CCC_EXPECT_CHAR(input, ':', "identifier");
|
||||
if(*input == '/') {
|
||||
input++;
|
||||
|
||||
Result<StabsStructOrUnionType::Visibility> visibility = parse_visibility_character(input);
|
||||
CCC_RETURN_IF_ERROR(visibility);
|
||||
field.visibility = *visibility;
|
||||
}
|
||||
if(*input == ':') {
|
||||
input = before_field;
|
||||
break;
|
||||
}
|
||||
auto type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(type);
|
||||
field.type = std::move(*type);
|
||||
|
||||
if(field.name.size() >= 1 && field.name[0] == '$') {
|
||||
// Virtual function table pointers and virtual base class pointers.
|
||||
CCC_EXPECT_CHAR(input, ',', "field type");
|
||||
|
||||
std::optional<s32> offset_bits = parse_number_s32(input);
|
||||
CCC_CHECK(offset_bits.has_value(), "Failed to parse field offset.");
|
||||
field.offset_bits = *offset_bits;
|
||||
|
||||
CCC_EXPECT_CHAR(input, ';', "field offset");
|
||||
} else if(*input == ':') {
|
||||
// Static fields.
|
||||
input++;
|
||||
field.is_static = true;
|
||||
|
||||
std::optional<std::string> type_name = parse_stabs_identifier(input, ';');
|
||||
CCC_CHECK(type_name.has_value(), "Failed to parse static field type name.");
|
||||
|
||||
field.type_name = std::move(*type_name);
|
||||
|
||||
CCC_EXPECT_CHAR(input, ';', "identifier");
|
||||
} else if(*input == ',') {
|
||||
// Normal fields.
|
||||
input++;
|
||||
|
||||
std::optional<s32> offset_bits = parse_number_s32(input);
|
||||
CCC_CHECK(offset_bits.has_value(), "Failed to parse field offset.");
|
||||
field.offset_bits = *offset_bits;
|
||||
|
||||
CCC_EXPECT_CHAR(input, ',', "field offset");
|
||||
|
||||
std::optional<s32> size_bits = parse_number_s32(input);
|
||||
CCC_CHECK(size_bits.has_value(), "Failed to parse field size.");
|
||||
field.size_bits = *size_bits;
|
||||
|
||||
CCC_EXPECT_CHAR(input, ';', "field size");
|
||||
} else {
|
||||
return CCC_FAILURE("Expected ':' or ',', got '%c' (%hhx).", *input, *input);
|
||||
}
|
||||
|
||||
STABS_DEBUG(print_field(field);)
|
||||
|
||||
fields.emplace_back(std::move(field));
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
static Result<std::vector<StabsStructOrUnionType::MemberFunctionSet>> parse_member_functions(const char*& input)
|
||||
{
|
||||
// Check for if the next character is from an enclosing field list. If this
|
||||
// is the case, the next character will be ',' for normal fields and ':' for
|
||||
// static fields (see above).
|
||||
if(*input == ',' || *input == ':') {
|
||||
return std::vector<StabsStructOrUnionType::MemberFunctionSet>();
|
||||
}
|
||||
|
||||
std::vector<StabsStructOrUnionType::MemberFunctionSet> member_functions;
|
||||
while(*input != '\0') {
|
||||
if(*input == ';') {
|
||||
input++;
|
||||
break;
|
||||
}
|
||||
StabsStructOrUnionType::MemberFunctionSet member_function_set;
|
||||
|
||||
std::optional<std::string> name = parse_stabs_identifier(input, ':');
|
||||
CCC_CHECK(name.has_value(), "Failed to parse member function name.");
|
||||
member_function_set.name = std::move(*name);
|
||||
|
||||
CCC_EXPECT_CHAR(input, ':', "member function");
|
||||
CCC_EXPECT_CHAR(input, ':', "member function");
|
||||
while(*input != '\0') {
|
||||
if(*input == ';') {
|
||||
input++;
|
||||
break;
|
||||
}
|
||||
|
||||
StabsStructOrUnionType::MemberFunction function;
|
||||
|
||||
auto type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(type);
|
||||
function.type = std::move(*type);
|
||||
|
||||
CCC_EXPECT_CHAR(input, ':', "member function");
|
||||
std::optional<std::string> identifier = parse_stabs_identifier(input, ';');
|
||||
CCC_CHECK(identifier.has_value(), "Invalid member function identifier.");
|
||||
|
||||
CCC_EXPECT_CHAR(input, ';', "member function");
|
||||
|
||||
Result<StabsStructOrUnionType::Visibility> visibility = parse_visibility_character(input);
|
||||
CCC_RETURN_IF_ERROR(visibility);
|
||||
function.visibility = *visibility;
|
||||
|
||||
char modifiers = *(input++);
|
||||
CCC_CHECK(modifiers != '\0', "Failed to parse member function modifiers.");
|
||||
switch(modifiers) {
|
||||
case 'A':
|
||||
function.is_const = false;
|
||||
function.is_volatile = false;
|
||||
break;
|
||||
case 'B':
|
||||
function.is_const = true;
|
||||
function.is_volatile = false;
|
||||
break;
|
||||
case 'C':
|
||||
function.is_const = false;
|
||||
function.is_volatile = true;
|
||||
break;
|
||||
case 'D':
|
||||
function.is_const = true;
|
||||
function.is_volatile = true;
|
||||
break;
|
||||
case '?':
|
||||
case '.':
|
||||
break;
|
||||
default:
|
||||
return CCC_FAILURE("Invalid member function modifiers.");
|
||||
}
|
||||
|
||||
char flag = *(input++);
|
||||
CCC_CHECK(flag != '\0', "Failed to parse member function type.");
|
||||
switch(flag) {
|
||||
case '.': { // normal member function
|
||||
function.modifier = ast::MemberFunctionModifier::NONE;
|
||||
break;
|
||||
}
|
||||
case '?': { // static member function
|
||||
function.modifier = ast::MemberFunctionModifier::STATIC;
|
||||
break;
|
||||
}
|
||||
case '*': { // virtual member function
|
||||
std::optional<s32> vtable_index = parse_number_s32(input);
|
||||
CCC_CHECK(vtable_index.has_value(), "Failed to parse vtable index.");
|
||||
function.vtable_index = *vtable_index;
|
||||
|
||||
CCC_EXPECT_CHAR(input, ';', "virtual member function");
|
||||
|
||||
auto virtual_type = parse_stabs_type(input);
|
||||
CCC_RETURN_IF_ERROR(virtual_type);
|
||||
function.virtual_type = std::move(*virtual_type);
|
||||
|
||||
CCC_EXPECT_CHAR(input, ';', "virtual member function");
|
||||
function.modifier = ast::MemberFunctionModifier::VIRTUAL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return CCC_FAILURE("Invalid member function type.");
|
||||
}
|
||||
member_function_set.overloads.emplace_back(std::move(function));
|
||||
}
|
||||
STABS_DEBUG_PRINTF("member func: %s\n", member_function_set.name.c_str());
|
||||
member_functions.emplace_back(std::move(member_function_set));
|
||||
}
|
||||
return member_functions;
|
||||
}
|
||||
|
||||
static Result<StabsStructOrUnionType::Visibility> parse_visibility_character(const char*& input)
|
||||
{
|
||||
char visibility = *(input++);
|
||||
switch(visibility) {
|
||||
case '0': return StabsStructOrUnionType::Visibility::PRIVATE;
|
||||
case '1': return StabsStructOrUnionType::Visibility::PROTECTED;
|
||||
case '2': return StabsStructOrUnionType::Visibility::PUBLIC;
|
||||
case '9': return StabsStructOrUnionType::Visibility::PUBLIC_OPTIMIZED_OUT;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return CCC_FAILURE("Failed to parse visibility character.");
|
||||
}
|
||||
|
||||
std::optional<s32> parse_number_s32(const char*& input)
|
||||
{
|
||||
char* end;
|
||||
s64 value = strtoll(input, &end, 10);
|
||||
if(end == input) {
|
||||
return std::nullopt;
|
||||
}
|
||||
input = end;
|
||||
return (s32) value;
|
||||
}
|
||||
|
||||
std::optional<s64> parse_number_s64(const char*& input)
|
||||
{
|
||||
char* end;
|
||||
s64 value = strtoll(input, &end, 10);
|
||||
if(end == input) {
|
||||
return std::nullopt;
|
||||
}
|
||||
input = end;
|
||||
return value;
|
||||
}
|
||||
|
||||
std::optional<std::string> parse_stabs_identifier(const char*& input, char terminator)
|
||||
{
|
||||
const char* begin = input;
|
||||
for(; *input != '\0'; input++) {
|
||||
if(*input == terminator) {
|
||||
return std::string(begin, input);
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// The complexity here is because the input may contain an unescaped namespace
|
||||
// separator '::' even if the field terminator is supposed to be a colon, as
|
||||
// well as the raw contents of character literals. See test/ccc/stabs_tests.cpp
|
||||
// for some examples.
|
||||
Result<std::string> parse_dodgy_stabs_identifier(const char*& input, char terminator)
|
||||
{
|
||||
const char* begin = input;
|
||||
s32 template_depth = 0;
|
||||
|
||||
for(; *input != '\0'; input++) {
|
||||
// Skip past character literals.
|
||||
if(*input == '\'') {
|
||||
input++;
|
||||
if(*input == '\'') {
|
||||
input++; // Handle character literals containing a single quote.
|
||||
}
|
||||
while(*input != '\'' && *input != '\0') {
|
||||
input++;
|
||||
}
|
||||
if(*input == '\0') {
|
||||
break;
|
||||
}
|
||||
input++;
|
||||
}
|
||||
|
||||
// Keep track of the template depth so we know when to expect the
|
||||
// terminator character.
|
||||
if(*input == '<') {
|
||||
template_depth++;
|
||||
}
|
||||
if(*input == '>') {
|
||||
template_depth--;
|
||||
}
|
||||
|
||||
if(*input == terminator && template_depth == 0) {
|
||||
return std::string(begin, input);
|
||||
}
|
||||
}
|
||||
|
||||
return CCC_FAILURE(STAB_TRUNCATED_ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
STABS_DEBUG(
|
||||
|
||||
static void print_field(const StabsStructOrUnionType::Field& field)
|
||||
{
|
||||
printf("\t%04x %04x %04x %04x %s\n", field.offset_bits / 8, field.size_bits / 8, field.offset_bits, field.size_bits, field.name.c_str());
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
const char* stabs_field_visibility_to_string(StabsStructOrUnionType::Visibility visibility)
|
||||
{
|
||||
switch(visibility) {
|
||||
case StabsStructOrUnionType::Visibility::PRIVATE: return "private";
|
||||
case StabsStructOrUnionType::Visibility::PROTECTED: return "protected";
|
||||
case StabsStructOrUnionType::Visibility::PUBLIC: return "public";
|
||||
case StabsStructOrUnionType::Visibility::PUBLIC_OPTIMIZED_OUT: return "public_optimizedout";
|
||||
default: return "none";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
379
3rdparty/ccc/src/ccc/stabs.h
vendored
Normal file
379
3rdparty/ccc/src/ccc/stabs.h
vendored
Normal file
@@ -0,0 +1,379 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ast.h"
|
||||
#include "util.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
enum class StabsSymbolDescriptor : u8 {
|
||||
LOCAL_VARIABLE = '_',
|
||||
REFERENCE_PARAMETER_A = 'a',
|
||||
LOCAL_FUNCTION = 'f',
|
||||
GLOBAL_FUNCTION = 'F',
|
||||
GLOBAL_VARIABLE = 'G',
|
||||
REGISTER_PARAMETER = 'P',
|
||||
VALUE_PARAMETER = 'p',
|
||||
REGISTER_VARIABLE = 'r',
|
||||
STATIC_GLOBAL_VARIABLE = 'S',
|
||||
TYPE_NAME = 't',
|
||||
ENUM_STRUCT_OR_TYPE_TAG = 'T',
|
||||
STATIC_LOCAL_VARIABLE = 'V',
|
||||
REFERENCE_PARAMETER_V = 'v'
|
||||
};
|
||||
|
||||
struct StabsType;
|
||||
|
||||
struct StabsSymbol {
|
||||
StabsSymbolDescriptor descriptor;
|
||||
std::string name;
|
||||
std::unique_ptr<StabsType> type;
|
||||
};
|
||||
|
||||
Result<StabsSymbol> parse_stabs_symbol(const char*& input);
|
||||
|
||||
enum class StabsTypeDescriptor : u8 {
|
||||
TYPE_REFERENCE = 0xef, // '0'..'9','('
|
||||
ARRAY = 'a',
|
||||
ENUM = 'e',
|
||||
FUNCTION = 'f',
|
||||
CONST_QUALIFIER = 'k',
|
||||
RANGE = 'r',
|
||||
STRUCT = 's',
|
||||
UNION = 'u',
|
||||
CROSS_REFERENCE = 'x',
|
||||
VOLATILE_QUALIFIER = 'B',
|
||||
FLOATING_POINT_BUILTIN = 'R',
|
||||
METHOD = '#',
|
||||
REFERENCE = '&',
|
||||
POINTER = '*',
|
||||
TYPE_ATTRIBUTE = '@',
|
||||
POINTER_TO_DATA_MEMBER = 0xee, // also '@'
|
||||
BUILTIN = '-'
|
||||
};
|
||||
|
||||
struct StabsBaseClass;
|
||||
struct StabsField;
|
||||
struct StabsMemberFunctionSet;
|
||||
|
||||
// e.g. for "123=*456" 123 would be the type_number, the type descriptor would
|
||||
// be of type POINTER and StabsPointerType::value_type would point to a type
|
||||
// with type_number = 456.
|
||||
struct StabsType {
|
||||
StabsTypeNumber type_number;
|
||||
// The name field is only populated for root types and cross references.
|
||||
std::optional<std::string> name;
|
||||
bool is_typedef = false;
|
||||
bool is_root = false;
|
||||
std::optional<StabsTypeDescriptor> descriptor;
|
||||
|
||||
StabsType(StabsTypeNumber n) : type_number(n) {}
|
||||
StabsType(StabsTypeDescriptor d) : descriptor(d) {}
|
||||
StabsType(StabsTypeNumber n, StabsTypeDescriptor d) : type_number(n), descriptor(d) {}
|
||||
virtual ~StabsType() {}
|
||||
|
||||
template <typename SubType>
|
||||
SubType& as()
|
||||
{
|
||||
CCC_ASSERT(descriptor == SubType::DESCRIPTOR);
|
||||
return *static_cast<SubType*>(this);
|
||||
}
|
||||
|
||||
template <typename SubType>
|
||||
const SubType& as() const
|
||||
{
|
||||
CCC_ASSERT(descriptor == SubType::DESCRIPTOR);
|
||||
return *static_cast<const SubType*>(this);
|
||||
}
|
||||
|
||||
virtual void enumerate_numbered_types(std::map<StabsTypeNumber, const StabsType*>& output) const
|
||||
{
|
||||
if(type_number.valid() && descriptor.has_value()) {
|
||||
output.emplace(type_number, this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct StabsTypeReferenceType : StabsType {
|
||||
std::unique_ptr<StabsType> type;
|
||||
|
||||
StabsTypeReferenceType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::TYPE_REFERENCE;
|
||||
|
||||
void enumerate_numbered_types(std::map<StabsTypeNumber, const StabsType*>& output) const override
|
||||
{
|
||||
StabsType::enumerate_numbered_types(output);
|
||||
type->enumerate_numbered_types(output);
|
||||
}
|
||||
};
|
||||
|
||||
struct StabsArrayType : StabsType {
|
||||
std::unique_ptr<StabsType> index_type;
|
||||
std::unique_ptr<StabsType> element_type;
|
||||
|
||||
StabsArrayType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::ARRAY;
|
||||
|
||||
void enumerate_numbered_types(std::map<StabsTypeNumber, const StabsType*>& output) const override
|
||||
{
|
||||
StabsType::enumerate_numbered_types(output);
|
||||
index_type->enumerate_numbered_types(output);
|
||||
element_type->enumerate_numbered_types(output);
|
||||
}
|
||||
};
|
||||
|
||||
struct StabsEnumType : StabsType {
|
||||
std::vector<std::pair<s32, std::string>> fields;
|
||||
|
||||
StabsEnumType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::ENUM;
|
||||
};
|
||||
|
||||
struct StabsFunctionType : StabsType {
|
||||
std::unique_ptr<StabsType> return_type;
|
||||
|
||||
StabsFunctionType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::FUNCTION;
|
||||
|
||||
void enumerate_numbered_types(std::map<StabsTypeNumber, const StabsType*>& output) const override
|
||||
{
|
||||
StabsType::enumerate_numbered_types(output);
|
||||
return_type->enumerate_numbered_types(output);
|
||||
}
|
||||
};
|
||||
|
||||
struct StabsVolatileQualifierType : StabsType {
|
||||
std::unique_ptr<StabsType> type;
|
||||
|
||||
StabsVolatileQualifierType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::VOLATILE_QUALIFIER;
|
||||
|
||||
void enumerate_numbered_types(std::map<StabsTypeNumber, const StabsType*>& output) const override
|
||||
{
|
||||
StabsType::enumerate_numbered_types(output);
|
||||
type->enumerate_numbered_types(output);
|
||||
}
|
||||
};
|
||||
|
||||
struct StabsConstQualifierType : StabsType {
|
||||
std::unique_ptr<StabsType> type;
|
||||
|
||||
StabsConstQualifierType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::CONST_QUALIFIER;
|
||||
|
||||
void enumerate_numbered_types(std::map<StabsTypeNumber, const StabsType*>& output) const override
|
||||
{
|
||||
StabsType::enumerate_numbered_types(output);
|
||||
type->enumerate_numbered_types(output);
|
||||
}
|
||||
};
|
||||
|
||||
struct StabsRangeType : StabsType {
|
||||
std::unique_ptr<StabsType> type;
|
||||
std::string low;
|
||||
std::string high; // Some compilers wrote out a wrapped around value here for zero (or variable?) length arrays.
|
||||
|
||||
StabsRangeType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::RANGE;
|
||||
|
||||
void enumerate_numbered_types(std::map<StabsTypeNumber, const StabsType*>& output) const override
|
||||
{
|
||||
StabsType::enumerate_numbered_types(output);
|
||||
type->enumerate_numbered_types(output);
|
||||
}
|
||||
};
|
||||
|
||||
struct StabsStructOrUnionType : StabsType {
|
||||
enum class Visibility : u8 {
|
||||
NONE,
|
||||
PRIVATE,
|
||||
PROTECTED,
|
||||
PUBLIC,
|
||||
PUBLIC_OPTIMIZED_OUT
|
||||
};
|
||||
|
||||
struct BaseClass {
|
||||
bool is_virtual;
|
||||
Visibility visibility;
|
||||
s32 offset = -1;
|
||||
std::unique_ptr<StabsType> type;
|
||||
};
|
||||
|
||||
struct Field {
|
||||
std::string name;
|
||||
Visibility visibility = Visibility::NONE;
|
||||
std::unique_ptr<StabsType> type;
|
||||
bool is_static = false;
|
||||
s32 offset_bits = 0;
|
||||
s32 size_bits = 0;
|
||||
std::string type_name;
|
||||
};
|
||||
|
||||
struct MemberFunction {
|
||||
std::unique_ptr<StabsType> type;
|
||||
std::unique_ptr<StabsType> virtual_type;
|
||||
Visibility visibility;
|
||||
bool is_const = false;
|
||||
bool is_volatile = false;
|
||||
ast::MemberFunctionModifier modifier = ast::MemberFunctionModifier::NONE;
|
||||
s32 vtable_index = -1;
|
||||
};
|
||||
|
||||
struct MemberFunctionSet {
|
||||
std::string name;
|
||||
std::vector<MemberFunction> overloads;
|
||||
};
|
||||
|
||||
s64 size = -1;
|
||||
std::vector<BaseClass> base_classes;
|
||||
std::vector<Field> fields;
|
||||
std::vector<MemberFunctionSet> member_functions;
|
||||
std::unique_ptr<StabsType> first_base_class;
|
||||
|
||||
StabsStructOrUnionType(StabsTypeNumber n, StabsTypeDescriptor d) : StabsType(n, d) {}
|
||||
|
||||
void enumerate_numbered_types(std::map<StabsTypeNumber, const StabsType*>& output) const override
|
||||
{
|
||||
StabsType::enumerate_numbered_types(output);
|
||||
for(const BaseClass& base_class : base_classes) {
|
||||
base_class.type->enumerate_numbered_types(output);
|
||||
}
|
||||
for(const Field& field : fields) {
|
||||
field.type->enumerate_numbered_types(output);
|
||||
}
|
||||
for(const MemberFunctionSet& member_function_set : member_functions) {
|
||||
for(const MemberFunction& member_function : member_function_set.overloads) {
|
||||
member_function.type->enumerate_numbered_types(output);
|
||||
if(member_function.virtual_type.get()) {
|
||||
member_function.virtual_type->enumerate_numbered_types(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(first_base_class.get()) {
|
||||
first_base_class->enumerate_numbered_types(output);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct StabsStructType : StabsStructOrUnionType {
|
||||
StabsStructType(StabsTypeNumber n) : StabsStructOrUnionType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::STRUCT;
|
||||
};
|
||||
|
||||
struct StabsUnionType : StabsStructOrUnionType {
|
||||
StabsUnionType(StabsTypeNumber n) : StabsStructOrUnionType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::UNION;
|
||||
};
|
||||
|
||||
|
||||
struct StabsCrossReferenceType : StabsType {
|
||||
ast::ForwardDeclaredType type;
|
||||
std::string identifier;
|
||||
|
||||
StabsCrossReferenceType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::CROSS_REFERENCE;
|
||||
};
|
||||
|
||||
struct StabsFloatingPointBuiltInType : StabsType {
|
||||
s32 fpclass = -1;
|
||||
s32 bytes = -1;
|
||||
|
||||
StabsFloatingPointBuiltInType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::FLOATING_POINT_BUILTIN;
|
||||
};
|
||||
|
||||
struct StabsMethodType : StabsType {
|
||||
std::unique_ptr<StabsType> return_type;
|
||||
std::optional<std::unique_ptr<StabsType>> class_type;
|
||||
std::vector<std::unique_ptr<StabsType>> parameter_types;
|
||||
|
||||
StabsMethodType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::METHOD;
|
||||
|
||||
void enumerate_numbered_types(std::map<StabsTypeNumber, const StabsType*>& output) const override
|
||||
{
|
||||
StabsType::enumerate_numbered_types(output);
|
||||
return_type->enumerate_numbered_types(output);
|
||||
if(class_type.has_value()) {
|
||||
(*class_type)->enumerate_numbered_types(output);
|
||||
}
|
||||
for(const std::unique_ptr<StabsType>& parameter_type : parameter_types) {
|
||||
parameter_type->enumerate_numbered_types(output);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct StabsReferenceType : StabsType {
|
||||
std::unique_ptr<StabsType> value_type;
|
||||
|
||||
StabsReferenceType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::REFERENCE;
|
||||
|
||||
void enumerate_numbered_types(std::map<StabsTypeNumber, const StabsType*>& output) const override
|
||||
{
|
||||
StabsType::enumerate_numbered_types(output);
|
||||
value_type->enumerate_numbered_types(output);
|
||||
}
|
||||
};
|
||||
|
||||
struct StabsPointerType : StabsType {
|
||||
std::unique_ptr<StabsType> value_type;
|
||||
|
||||
StabsPointerType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::POINTER;
|
||||
|
||||
void enumerate_numbered_types(std::map<StabsTypeNumber, const StabsType*>& output) const override
|
||||
{
|
||||
StabsType::enumerate_numbered_types(output);
|
||||
value_type->enumerate_numbered_types(output);
|
||||
}
|
||||
};
|
||||
|
||||
struct StabsSizeTypeAttributeType : StabsType {
|
||||
s64 size_bits = -1;
|
||||
std::unique_ptr<StabsType> type;
|
||||
|
||||
StabsSizeTypeAttributeType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::TYPE_ATTRIBUTE;
|
||||
|
||||
void enumerate_numbered_types(std::map<StabsTypeNumber, const StabsType*>& output) const override
|
||||
{
|
||||
StabsType::enumerate_numbered_types(output);
|
||||
type->enumerate_numbered_types(output);
|
||||
}
|
||||
};
|
||||
|
||||
struct StabsPointerToDataMemberType : StabsType {
|
||||
std::unique_ptr<StabsType> class_type;
|
||||
std::unique_ptr<StabsType> member_type;
|
||||
|
||||
StabsPointerToDataMemberType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::POINTER_TO_DATA_MEMBER;
|
||||
|
||||
void enumerate_numbered_types(std::map<StabsTypeNumber, const StabsType*>& output) const override
|
||||
{
|
||||
StabsType::enumerate_numbered_types(output);
|
||||
class_type->enumerate_numbered_types(output);
|
||||
member_type->enumerate_numbered_types(output);
|
||||
}
|
||||
};
|
||||
|
||||
struct StabsBuiltInType : StabsType {
|
||||
s64 type_id = -1;
|
||||
|
||||
StabsBuiltInType(StabsTypeNumber n) : StabsType(n, DESCRIPTOR) {}
|
||||
static const constexpr StabsTypeDescriptor DESCRIPTOR = StabsTypeDescriptor::BUILTIN;
|
||||
};
|
||||
|
||||
extern const char* STAB_TRUNCATED_ERROR_MESSAGE;
|
||||
|
||||
Result<std::unique_ptr<StabsType>> parse_top_level_stabs_type(const char*& input);
|
||||
std::optional<s32> parse_number_s32(const char*& input);
|
||||
std::optional<s64> parse_number_s64(const char*& input);
|
||||
std::optional<std::string> parse_stabs_identifier(const char*& input, char terminator);
|
||||
Result<std::string> parse_dodgy_stabs_identifier(const char*& input, char terminator);
|
||||
const char* stabs_field_visibility_to_string(StabsStructOrUnionType::Visibility visibility);
|
||||
|
||||
}
|
||||
834
3rdparty/ccc/src/ccc/stabs_to_ast.cpp
vendored
Normal file
834
3rdparty/ccc/src/ccc/stabs_to_ast.cpp
vendored
Normal file
@@ -0,0 +1,834 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "stabs_to_ast.h"
|
||||
|
||||
#include "importer_flags.h"
|
||||
|
||||
#define AST_DEBUG(...) //__VA_ARGS__
|
||||
#define AST_DEBUG_PRINTF(...) AST_DEBUG(printf(__VA_ARGS__);)
|
||||
|
||||
namespace ccc {
|
||||
|
||||
struct MemberFunctionInfo {
|
||||
std::string name;
|
||||
bool is_constructor_or_destructor = false;
|
||||
bool is_special_member_function = false;
|
||||
bool is_operator_member_function = false;
|
||||
};
|
||||
|
||||
static bool is_void_like(const StabsType& type);
|
||||
static Result<ast::BuiltInClass> classify_range(const StabsRangeType& type);
|
||||
static Result<std::unique_ptr<ast::Node>> field_to_ast(
|
||||
const StabsStructOrUnionType::Field& field,
|
||||
const StabsType& enclosing_struct,
|
||||
const StabsToAstState& state,
|
||||
s32 depth);
|
||||
static Result<bool> detect_bitfield(const StabsStructOrUnionType::Field& field, const StabsToAstState& state);
|
||||
static Result<std::vector<std::unique_ptr<ast::Node>>> member_functions_to_ast(
|
||||
const StabsStructOrUnionType& type, const StabsToAstState& state, s32 depth);
|
||||
static MemberFunctionInfo check_member_function(
|
||||
const std::string& mangled_name,
|
||||
std::string_view type_name_no_template_args,
|
||||
const DemanglerFunctions& demangler,
|
||||
u32 importer_flags);
|
||||
|
||||
Result<std::unique_ptr<ast::Node>> stabs_type_to_ast(
|
||||
const StabsType& type,
|
||||
const StabsType* enclosing_struct,
|
||||
const StabsToAstState& state,
|
||||
s32 depth,
|
||||
bool substitute_type_name,
|
||||
bool force_substitute)
|
||||
{
|
||||
AST_DEBUG_PRINTF("%-*stype desc=%hhx '%c' num=(%d,%d) name=%s\n",
|
||||
depth * 4, "",
|
||||
type.descriptor.has_value() ? (u8) *type.descriptor : 'X',
|
||||
(type.descriptor.has_value() && isprint((u8) *type.descriptor)) ? (u8) *type.descriptor : '!',
|
||||
type.type_number.file, type.type_number.type,
|
||||
type.name.has_value() ? type.name->c_str() : "");
|
||||
|
||||
if(depth > 200) {
|
||||
const char* error_message = "Call depth greater than 200 in stabs_type_to_ast, probably infinite recursion.";
|
||||
if(state.importer_flags & STRICT_PARSING) {
|
||||
return CCC_FAILURE(error_message);
|
||||
} else {
|
||||
CCC_WARN(error_message);
|
||||
|
||||
auto error = std::make_unique<ast::Error>();
|
||||
error->message = error_message;
|
||||
return std::unique_ptr<ast::Node>(std::move(error));
|
||||
}
|
||||
}
|
||||
|
||||
// This makes sure that types are replaced with their type name in cases
|
||||
// where that would be more appropriate.
|
||||
if(type.name.has_value()) {
|
||||
bool try_substitute = depth > 0 && (type.is_root
|
||||
|| type.descriptor == StabsTypeDescriptor::RANGE
|
||||
|| type.descriptor == StabsTypeDescriptor::BUILTIN);
|
||||
// GCC emits anonymous enums with a name of " " since apparently some
|
||||
// debuggers can't handle zero-length names.
|
||||
bool is_name_empty = type.name == "" || type.name == " ";
|
||||
// Cross references will be handled below.
|
||||
bool is_cross_reference = type.descriptor == StabsTypeDescriptor::CROSS_REFERENCE;
|
||||
bool is_void = is_void_like(type);
|
||||
if((substitute_type_name || try_substitute) && !is_name_empty && !is_cross_reference && !is_void) {
|
||||
auto type_name = std::make_unique<ast::TypeName>();
|
||||
type_name->source = ast::TypeNameSource::REFERENCE;
|
||||
type_name->unresolved_stabs = std::make_unique<ast::TypeName::UnresolvedStabs>();
|
||||
type_name->unresolved_stabs->type_name = *type.name;
|
||||
type_name->unresolved_stabs->referenced_file_handle = state.file_handle;
|
||||
type_name->unresolved_stabs->stabs_type_number = type.type_number;
|
||||
return std::unique_ptr<ast::Node>(std::move(type_name));
|
||||
}
|
||||
}
|
||||
|
||||
// This prevents infinite recursion when an automatically generated member
|
||||
// function references an unnamed type.
|
||||
bool can_compare_type_numbers = type.type_number.valid() && enclosing_struct && enclosing_struct->type_number.valid();
|
||||
if(force_substitute && can_compare_type_numbers && type.type_number == enclosing_struct->type_number) {
|
||||
// It's probably a this parameter (or return type) for an unnamed type.
|
||||
auto type_name = std::make_unique<ast::TypeName>();
|
||||
type_name->source = ast::TypeNameSource::UNNAMED_THIS;
|
||||
type_name->unresolved_stabs = std::make_unique<ast::TypeName::UnresolvedStabs>();
|
||||
type_name->unresolved_stabs->type_name = enclosing_struct->name.has_value() ? *enclosing_struct->name : "";
|
||||
type_name->unresolved_stabs->referenced_file_handle = state.file_handle;
|
||||
type_name->unresolved_stabs->stabs_type_number = type.type_number;
|
||||
return std::unique_ptr<ast::Node>(std::move(type_name));
|
||||
}
|
||||
|
||||
if(!type.descriptor.has_value()) {
|
||||
// The definition of the type has been defined previously, so we have to
|
||||
// look it up by its type number.
|
||||
CCC_CHECK(type.type_number.valid(), "Cannot lookup type (type is anonymous).");
|
||||
auto stabs_type = state.stabs_types->find(type.type_number);
|
||||
if(stabs_type == state.stabs_types->end()) {
|
||||
std::string error_message = "Failed to lookup STABS type by its type number ("
|
||||
+ std::to_string(type.type_number.file) + "," + std::to_string(type.type_number.type) + ").";
|
||||
if(state.importer_flags & STRICT_PARSING) {
|
||||
return CCC_FAILURE("%s", error_message.c_str());
|
||||
} else {
|
||||
CCC_WARN("%s", error_message.c_str());
|
||||
std::unique_ptr<ast::Error> error = std::make_unique<ast::Error>();
|
||||
error->message = std::move(error_message);
|
||||
return std::unique_ptr<ast::Node>(std::move(error));
|
||||
}
|
||||
}
|
||||
return stabs_type_to_ast(
|
||||
*stabs_type->second,
|
||||
enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
substitute_type_name,
|
||||
force_substitute);
|
||||
}
|
||||
|
||||
std::unique_ptr<ast::Node> result;
|
||||
|
||||
switch(*type.descriptor) {
|
||||
case StabsTypeDescriptor::TYPE_REFERENCE: {
|
||||
const auto& stabs_type_ref = type.as<StabsTypeReferenceType>();
|
||||
if(!type.type_number.valid() || !stabs_type_ref.type->type_number.valid() || stabs_type_ref.type->type_number != type.type_number) {
|
||||
auto node = stabs_type_to_ast(
|
||||
*stabs_type_ref.type,
|
||||
enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
substitute_type_name,
|
||||
force_substitute);
|
||||
CCC_RETURN_IF_ERROR(node);
|
||||
result = std::move(*node);
|
||||
} else {
|
||||
// I still don't know why in STABS void is a reference to
|
||||
// itself, maybe because I'm not a philosopher.
|
||||
auto builtin = std::make_unique<ast::BuiltIn>();
|
||||
builtin->bclass = ast::BuiltInClass::VOID_TYPE;
|
||||
result = std::move(builtin);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::ARRAY: {
|
||||
auto array = std::make_unique<ast::Array>();
|
||||
const auto& stabs_array = type.as<StabsArrayType>();
|
||||
|
||||
auto element_node = stabs_type_to_ast(
|
||||
*stabs_array.element_type,
|
||||
enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
true,
|
||||
force_substitute);
|
||||
CCC_RETURN_IF_ERROR(element_node);
|
||||
array->element_type = std::move(*element_node);
|
||||
|
||||
const StabsRangeType& index = stabs_array.index_type->as<StabsRangeType>();
|
||||
|
||||
char* end = nullptr;
|
||||
|
||||
const char* low = index.low.c_str();
|
||||
s64 low_value = strtoll(low, &end, 10);
|
||||
CCC_CHECK(end != low, "Failed to parse low part of range as integer.");
|
||||
CCC_CHECK(low_value == 0, "Invalid index type for array.");
|
||||
|
||||
const char* high = index.high.c_str();
|
||||
s64 high_value = strtoll(high, &end, 10);
|
||||
CCC_CHECK(end != high, "Failed to parse low part of range as integer.");
|
||||
|
||||
if(high_value == 4294967295) {
|
||||
// Some compilers wrote out a wrapped around value here.
|
||||
array->element_count = 0;
|
||||
} else {
|
||||
array->element_count = (s32) high_value + 1;
|
||||
}
|
||||
|
||||
result = std::move(array);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::ENUM: {
|
||||
auto inline_enum = std::make_unique<ast::Enum>();
|
||||
const auto& stabs_enum = type.as<StabsEnumType>();
|
||||
inline_enum->constants = stabs_enum.fields;
|
||||
result = std::move(inline_enum);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::FUNCTION: {
|
||||
auto function = std::make_unique<ast::Function>();
|
||||
|
||||
auto node = stabs_type_to_ast(
|
||||
*type.as<StabsFunctionType>().return_type,
|
||||
enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
true,
|
||||
force_substitute);
|
||||
CCC_RETURN_IF_ERROR(node);
|
||||
function->return_type = std::move(*node);
|
||||
|
||||
result = std::move(function);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::VOLATILE_QUALIFIER: {
|
||||
const auto& volatile_qualifier = type.as<StabsVolatileQualifierType>();
|
||||
|
||||
auto node = stabs_type_to_ast(
|
||||
*volatile_qualifier.type.get(),
|
||||
enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
substitute_type_name,
|
||||
force_substitute);
|
||||
CCC_RETURN_IF_ERROR(node);
|
||||
result = std::move(*node);
|
||||
|
||||
result->is_volatile = true;
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::CONST_QUALIFIER: {
|
||||
const auto& const_qualifier = type.as<StabsConstQualifierType>();
|
||||
|
||||
auto node = stabs_type_to_ast(
|
||||
*const_qualifier.type.get(),
|
||||
enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
substitute_type_name,
|
||||
force_substitute);
|
||||
result = std::move(*node);
|
||||
|
||||
result->is_const = true;
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::RANGE: {
|
||||
auto builtin = std::make_unique<ast::BuiltIn>();
|
||||
Result<ast::BuiltInClass> bclass = classify_range(type.as<StabsRangeType>());
|
||||
CCC_RETURN_IF_ERROR(bclass);
|
||||
builtin->bclass = *bclass;
|
||||
result = std::move(builtin);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::STRUCT:
|
||||
case StabsTypeDescriptor::UNION: {
|
||||
const StabsStructOrUnionType* stabs_struct_or_union;
|
||||
if(type.descriptor == StabsTypeDescriptor::STRUCT) {
|
||||
stabs_struct_or_union = &type.as<StabsStructType>();
|
||||
} else {
|
||||
stabs_struct_or_union = &type.as<StabsUnionType>();
|
||||
}
|
||||
|
||||
auto struct_or_union = std::make_unique<ast::StructOrUnion>();
|
||||
struct_or_union->is_struct = type.descriptor == StabsTypeDescriptor::STRUCT;
|
||||
struct_or_union->size_bits = (s32) stabs_struct_or_union->size * 8;
|
||||
|
||||
for(const StabsStructOrUnionType::BaseClass& stabs_base_class : stabs_struct_or_union->base_classes) {
|
||||
auto base_class = stabs_type_to_ast(
|
||||
*stabs_base_class.type,
|
||||
&type,
|
||||
state,
|
||||
depth + 1,
|
||||
true,
|
||||
force_substitute);
|
||||
CCC_RETURN_IF_ERROR(base_class);
|
||||
|
||||
(*base_class)->offset_bytes = stabs_base_class.offset;
|
||||
(*base_class)->set_access_specifier(stabs_field_visibility_to_access_specifier(stabs_base_class.visibility), state.importer_flags);
|
||||
|
||||
if(stabs_base_class.is_virtual) {
|
||||
(*base_class)->is_virtual_base_class = true;
|
||||
}
|
||||
|
||||
struct_or_union->base_classes.emplace_back(std::move(*base_class));
|
||||
}
|
||||
|
||||
AST_DEBUG_PRINTF("%-*s beginfields\n", depth * 4, "");
|
||||
for(const StabsStructOrUnionType::Field& field : stabs_struct_or_union->fields) {
|
||||
auto node = field_to_ast(field, type, state, depth);
|
||||
CCC_RETURN_IF_ERROR(node);
|
||||
struct_or_union->fields.emplace_back(std::move(*node));
|
||||
}
|
||||
AST_DEBUG_PRINTF("%-*s endfields\n", depth * 4, "");
|
||||
|
||||
AST_DEBUG_PRINTF("%-*s beginmemberfuncs\n", depth * 4, "");
|
||||
Result<std::vector<std::unique_ptr<ast::Node>>> member_functions =
|
||||
member_functions_to_ast(*stabs_struct_or_union, state, depth);
|
||||
CCC_RETURN_IF_ERROR(member_functions);
|
||||
struct_or_union->member_functions = std::move(*member_functions);
|
||||
AST_DEBUG_PRINTF("%-*s endmemberfuncs\n", depth * 4, "");
|
||||
|
||||
result = std::move(struct_or_union);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::CROSS_REFERENCE: {
|
||||
const auto& cross_reference = type.as<StabsCrossReferenceType>();
|
||||
auto type_name = std::make_unique<ast::TypeName>();
|
||||
type_name->source = ast::TypeNameSource::CROSS_REFERENCE;
|
||||
type_name->unresolved_stabs = std::make_unique<ast::TypeName::UnresolvedStabs>();
|
||||
type_name->unresolved_stabs->type_name = cross_reference.identifier;
|
||||
type_name->unresolved_stabs->type = cross_reference.type;
|
||||
result = std::move(type_name);
|
||||
break;
|
||||
}
|
||||
case ccc::StabsTypeDescriptor::FLOATING_POINT_BUILTIN: {
|
||||
const auto& fp_builtin = type.as<StabsFloatingPointBuiltInType>();
|
||||
auto builtin = std::make_unique<ast::BuiltIn>();
|
||||
switch(fp_builtin.bytes) {
|
||||
case 1: builtin->bclass = ast::BuiltInClass::UNSIGNED_8; break;
|
||||
case 2: builtin->bclass = ast::BuiltInClass::UNSIGNED_16; break;
|
||||
case 4: builtin->bclass = ast::BuiltInClass::UNSIGNED_32; break;
|
||||
case 8: builtin->bclass = ast::BuiltInClass::UNSIGNED_64; break;
|
||||
case 16: builtin->bclass = ast::BuiltInClass::UNSIGNED_128; break;
|
||||
default: builtin->bclass = ast::BuiltInClass::UNSIGNED_8; break;
|
||||
}
|
||||
result = std::move(builtin);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::METHOD: {
|
||||
const auto& stabs_method = type.as<StabsMethodType>();
|
||||
auto function = std::make_unique<ast::Function>();
|
||||
|
||||
auto return_node = stabs_type_to_ast(
|
||||
*stabs_method.return_type.get(),
|
||||
enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
true,
|
||||
true);
|
||||
CCC_RETURN_IF_ERROR(return_node);
|
||||
function->return_type = std::move(*return_node);
|
||||
|
||||
function->parameters.emplace();
|
||||
for(const std::unique_ptr<StabsType>& parameter_type : stabs_method.parameter_types) {
|
||||
auto parameter_node = stabs_type_to_ast(
|
||||
*parameter_type,
|
||||
enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
true,
|
||||
true);
|
||||
CCC_RETURN_IF_ERROR(parameter_node);
|
||||
function->parameters->emplace_back(std::move(*parameter_node));
|
||||
}
|
||||
result = std::move(function);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::POINTER: {
|
||||
auto pointer = std::make_unique<ast::PointerOrReference>();
|
||||
pointer->is_pointer = true;
|
||||
|
||||
auto value_node = stabs_type_to_ast(
|
||||
*type.as<StabsPointerType>().value_type,
|
||||
enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
true,
|
||||
force_substitute);
|
||||
CCC_RETURN_IF_ERROR(value_node);
|
||||
pointer->value_type = std::move(*value_node);
|
||||
|
||||
result = std::move(pointer);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::REFERENCE: {
|
||||
auto reference = std::make_unique<ast::PointerOrReference>();
|
||||
reference->is_pointer = false;
|
||||
|
||||
auto value_node = stabs_type_to_ast(
|
||||
*type.as<StabsReferenceType>().value_type,
|
||||
enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
true,
|
||||
force_substitute);
|
||||
CCC_RETURN_IF_ERROR(value_node);
|
||||
reference->value_type = std::move(*value_node);
|
||||
|
||||
result = std::move(reference);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::TYPE_ATTRIBUTE: {
|
||||
const auto& stabs_type_attribute = type.as<StabsSizeTypeAttributeType>();
|
||||
|
||||
auto node = stabs_type_to_ast(
|
||||
*stabs_type_attribute.type,
|
||||
enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
substitute_type_name,
|
||||
force_substitute);
|
||||
CCC_RETURN_IF_ERROR(node);
|
||||
result = std::move(*node);
|
||||
|
||||
result->size_bits = (s32) stabs_type_attribute.size_bits;
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::POINTER_TO_DATA_MEMBER: {
|
||||
const auto& stabs_member_pointer = type.as<StabsPointerToDataMemberType>();
|
||||
auto member_pointer = std::make_unique<ast::PointerToDataMember>();
|
||||
|
||||
auto class_node = stabs_type_to_ast(
|
||||
*stabs_member_pointer.class_type.get(),
|
||||
enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
true,
|
||||
true);
|
||||
CCC_RETURN_IF_ERROR(class_node);
|
||||
member_pointer->class_type = std::move(*class_node);
|
||||
|
||||
auto member_node = stabs_type_to_ast(
|
||||
*stabs_member_pointer.member_type.get(),
|
||||
enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
true,
|
||||
true);
|
||||
CCC_RETURN_IF_ERROR(member_node);
|
||||
member_pointer->member_type = std::move(*member_node);
|
||||
|
||||
result = std::move(member_pointer);
|
||||
break;
|
||||
}
|
||||
case StabsTypeDescriptor::BUILTIN: {
|
||||
CCC_CHECK(type.as<StabsBuiltInType>().type_id == 16,
|
||||
"Unknown built-in type!");
|
||||
auto builtin = std::make_unique<ast::BuiltIn>();
|
||||
builtin->bclass = ast::BuiltInClass::BOOL_8;
|
||||
result = std::move(builtin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CCC_CHECK(result, "Result of stabs_type_to_ast call is nullptr.");
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool is_void_like(const StabsType& type)
|
||||
{
|
||||
// Unfortunately, a common case seems to be that various types (most
|
||||
// commonly __builtin_va_list) are indistinguishable from void or void*, so
|
||||
// we have to output them as a void built-in.
|
||||
if(type.descriptor.has_value()) {
|
||||
switch(*type.descriptor) {
|
||||
case StabsTypeDescriptor::POINTER: {
|
||||
return is_void_like(*type.as<StabsPointerType>().value_type.get());
|
||||
}
|
||||
case StabsTypeDescriptor::TYPE_REFERENCE: {
|
||||
return type.as<StabsTypeReferenceType>().type->type_number == type.type_number;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static Result<ast::BuiltInClass> classify_range(const StabsRangeType& type)
|
||||
{
|
||||
const char* low = type.low.c_str();
|
||||
const char* high = type.high.c_str();
|
||||
|
||||
// Handle some special cases and values that are too large to easily store
|
||||
// in a 64-bit integer.
|
||||
static const struct { const char* low; const char* high; ast::BuiltInClass classification; } strings[] = {
|
||||
{"4", "0", ast::BuiltInClass::FLOAT_32},
|
||||
{"000000000000000000000000", "001777777777777777777777", ast::BuiltInClass::UNSIGNED_64},
|
||||
{"00000000000000000000000000000000000000000000", "00000000000000000000001777777777777777777777", ast::BuiltInClass::UNSIGNED_64},
|
||||
{"0000000000000", "01777777777777777777777", ast::BuiltInClass::UNSIGNED_64}, // IOP
|
||||
{"0", "18446744073709551615", ast::BuiltInClass::UNSIGNED_64},
|
||||
{"001000000000000000000000", "000777777777777777777777", ast::BuiltInClass::SIGNED_64},
|
||||
{"00000000000000000000001000000000000000000000", "00000000000000000000000777777777777777777777", ast::BuiltInClass::SIGNED_64},
|
||||
{"01000000000000000000000", "0777777777777777777777", ast::BuiltInClass::SIGNED_64}, // IOP
|
||||
{"-9223372036854775808", "9223372036854775807", ast::BuiltInClass::SIGNED_64},
|
||||
{"8", "0", ast::BuiltInClass::FLOAT_64},
|
||||
{"00000000000000000000000000000000000000000000", "03777777777777777777777777777777777777777777", ast::BuiltInClass::UNSIGNED_128},
|
||||
{"02000000000000000000000000000000000000000000", "01777777777777777777777777777777777777777777", ast::BuiltInClass::SIGNED_128},
|
||||
{"000000000000000000000000", "0377777777777777777777777777777777", ast::BuiltInClass::UNQUALIFIED_128},
|
||||
{"16", "0", ast::BuiltInClass::FLOAT_128},
|
||||
{"0", "-1", ast::BuiltInClass::UNQUALIFIED_128} // Old homebrew toolchain
|
||||
};
|
||||
|
||||
for(const auto& range : strings) {
|
||||
if(strcmp(range.low, low) == 0 && strcmp(range.high, high) == 0) {
|
||||
return range.classification;
|
||||
}
|
||||
}
|
||||
|
||||
// For smaller values we actually parse the bounds as integers.
|
||||
char* end = nullptr;
|
||||
s64 low_value = strtoll(type.low.c_str(), &end, low[0] == '0' ? 8 : 10);
|
||||
CCC_CHECK(end != low, "Failed to parse low part of range as integer.");
|
||||
s64 high_value = strtoll(type.high.c_str(), &end, high[0] == '0' ? 8 : 10);
|
||||
CCC_CHECK(end != high, "Failed to parse high part of range as integer.");
|
||||
|
||||
static const struct { s64 low; s64 high; ast::BuiltInClass classification; } integers[] = {
|
||||
{0, 255, ast::BuiltInClass::UNSIGNED_8},
|
||||
{-128, 127, ast::BuiltInClass::SIGNED_8},
|
||||
{0, 127, ast::BuiltInClass::UNQUALIFIED_8},
|
||||
{0, 65535, ast::BuiltInClass::UNSIGNED_16},
|
||||
{-32768, 32767, ast::BuiltInClass::SIGNED_16},
|
||||
{0, 4294967295, ast::BuiltInClass::UNSIGNED_32},
|
||||
{-2147483648, 2147483647, ast::BuiltInClass::SIGNED_32},
|
||||
};
|
||||
|
||||
for(const auto& range : integers) {
|
||||
if((range.low == low_value || range.low == -low_value) && range.high == high_value) {
|
||||
return range.classification;
|
||||
}
|
||||
}
|
||||
|
||||
return CCC_FAILURE("Failed to classify range.");
|
||||
}
|
||||
|
||||
static Result<std::unique_ptr<ast::Node>> field_to_ast(
|
||||
const StabsStructOrUnionType::Field& field,
|
||||
const StabsType& enclosing_struct,
|
||||
const StabsToAstState& state,
|
||||
s32 depth)
|
||||
{
|
||||
AST_DEBUG_PRINTF("%-*s field %s\n", depth * 4, "", field.name.c_str());
|
||||
|
||||
Result<bool> is_bitfield = detect_bitfield(field, state);
|
||||
CCC_RETURN_IF_ERROR(is_bitfield);
|
||||
|
||||
if(*is_bitfield) {
|
||||
// Process bitfields.
|
||||
auto bitfield_node = stabs_type_to_ast(
|
||||
*field.type,
|
||||
&enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
true,
|
||||
false);
|
||||
CCC_RETURN_IF_ERROR(bitfield_node);
|
||||
|
||||
std::unique_ptr<ast::BitField> bitfield = std::make_unique<ast::BitField>();
|
||||
bitfield->name = (field.name == " ") ? "" : field.name;
|
||||
bitfield->offset_bytes = field.offset_bits / 8;
|
||||
bitfield->size_bits = field.size_bits;
|
||||
bitfield->underlying_type = std::move(*bitfield_node);
|
||||
bitfield->bitfield_offset_bits = field.offset_bits % 8;
|
||||
bitfield->set_access_specifier(stabs_field_visibility_to_access_specifier(field.visibility), state.importer_flags);
|
||||
|
||||
return std::unique_ptr<ast::Node>(std::move(bitfield));
|
||||
} else {
|
||||
// Process a normal field.
|
||||
Result<std::unique_ptr<ast::Node>> node = stabs_type_to_ast(
|
||||
*field.type,
|
||||
&enclosing_struct,
|
||||
state,
|
||||
depth + 1,
|
||||
true,
|
||||
false);
|
||||
CCC_RETURN_IF_ERROR(node);
|
||||
|
||||
(*node)->name = field.name;
|
||||
(*node)->offset_bytes = field.offset_bits / 8;
|
||||
(*node)->size_bits = field.size_bits;
|
||||
(*node)->set_access_specifier(stabs_field_visibility_to_access_specifier(field.visibility), state.importer_flags);
|
||||
|
||||
if(field.name.starts_with("$vf") || field.name.starts_with("_vptr$") || field.name.starts_with("_vptr.")) {
|
||||
(*node)->is_vtable_pointer = true;
|
||||
}
|
||||
|
||||
if(field.is_static) {
|
||||
(*node)->storage_class = STORAGE_CLASS_STATIC;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
static Result<bool> detect_bitfield(const StabsStructOrUnionType::Field& field, const StabsToAstState& state)
|
||||
{
|
||||
// Static fields can't be bitfields.
|
||||
if(field.is_static) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Resolve type references.
|
||||
const StabsType* type = field.type.get();
|
||||
for(s32 i = 0; i < 50; i++) {
|
||||
if(!type->descriptor.has_value()) {
|
||||
if(!type->type_number.valid()) {
|
||||
return false;
|
||||
}
|
||||
auto next_type = state.stabs_types->find(type->type_number);
|
||||
if(next_type == state.stabs_types->end() || next_type->second == type) {
|
||||
return false;
|
||||
}
|
||||
type = next_type->second;
|
||||
} else if(type->descriptor == StabsTypeDescriptor::TYPE_REFERENCE) {
|
||||
type = type->as<StabsTypeReferenceType>().type.get();
|
||||
} else if(type->descriptor == StabsTypeDescriptor::CONST_QUALIFIER) {
|
||||
type = type->as<StabsConstQualifierType>().type.get();
|
||||
} else if(type->descriptor == StabsTypeDescriptor::VOLATILE_QUALIFIER) {
|
||||
type = type->as<StabsVolatileQualifierType>().type.get();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
// Prevent an infinite loop if there's a cycle (fatal frame).
|
||||
if(i == 49) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the size of the underlying type.
|
||||
s32 underlying_type_size_bits = 0;
|
||||
switch(*type->descriptor) {
|
||||
case ccc::StabsTypeDescriptor::RANGE: {
|
||||
Result<ast::BuiltInClass> bclass = classify_range(type->as<StabsRangeType>());
|
||||
CCC_RETURN_IF_ERROR(bclass);
|
||||
underlying_type_size_bits = builtin_class_size(*bclass) * 8;
|
||||
break;
|
||||
}
|
||||
case ccc::StabsTypeDescriptor::CROSS_REFERENCE: {
|
||||
if(type->as<StabsCrossReferenceType>().type == ast::ForwardDeclaredType::ENUM) {
|
||||
underlying_type_size_bits = 32;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ccc::StabsTypeDescriptor::TYPE_ATTRIBUTE: {
|
||||
underlying_type_size_bits = (s32) type->as<StabsSizeTypeAttributeType>().size_bits;
|
||||
break;
|
||||
}
|
||||
case ccc::StabsTypeDescriptor::BUILTIN: {
|
||||
underlying_type_size_bits = 8; // bool
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(underlying_type_size_bits == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return field.size_bits != underlying_type_size_bits;
|
||||
}
|
||||
|
||||
static Result<std::vector<std::unique_ptr<ast::Node>>> member_functions_to_ast(
|
||||
const StabsStructOrUnionType& type, const StabsToAstState& state, s32 depth)
|
||||
{
|
||||
if(state.importer_flags & NO_MEMBER_FUNCTIONS) {
|
||||
return std::vector<std::unique_ptr<ast::Node>>();
|
||||
}
|
||||
|
||||
std::string_view type_name_no_template_args;
|
||||
if(type.name.has_value()) {
|
||||
type_name_no_template_args =
|
||||
std::string_view(*type.name).substr(0, type.name->find("<"));
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<ast::Node>> member_functions;
|
||||
bool only_special_functions = true;
|
||||
|
||||
for(const StabsStructOrUnionType::MemberFunctionSet& function_set : type.member_functions) {
|
||||
MemberFunctionInfo info = check_member_function(
|
||||
function_set.name, type_name_no_template_args, state.demangler, state.importer_flags);
|
||||
|
||||
if(!info.is_special_member_function) {
|
||||
only_special_functions = false;
|
||||
}
|
||||
|
||||
for(const StabsStructOrUnionType::MemberFunction& stabs_func : function_set.overloads) {
|
||||
auto node = stabs_type_to_ast(
|
||||
*stabs_func.type,
|
||||
&type,
|
||||
state,
|
||||
depth + 1,
|
||||
true,
|
||||
true);
|
||||
CCC_RETURN_IF_ERROR(node);
|
||||
|
||||
(*node)->is_constructor_or_destructor = info.is_constructor_or_destructor;
|
||||
(*node)->is_special_member_function = info.is_special_member_function;
|
||||
(*node)->is_operator_member_function = info.is_operator_member_function;
|
||||
|
||||
(*node)->name = info.name;
|
||||
(*node)->set_access_specifier(stabs_field_visibility_to_access_specifier(stabs_func.visibility), state.importer_flags);
|
||||
|
||||
if((*node)->descriptor == ast::FUNCTION) {
|
||||
ast::Function& function = (*node)->as<ast::Function>();
|
||||
function.modifier = stabs_func.modifier;
|
||||
function.vtable_index = stabs_func.vtable_index;
|
||||
}
|
||||
|
||||
member_functions.emplace_back(std::move(*node));
|
||||
}
|
||||
}
|
||||
|
||||
if(only_special_functions && (state.importer_flags & INCLUDE_GENERATED_MEMBER_FUNCTIONS) == 0) {
|
||||
return std::vector<std::unique_ptr<ast::Node>>();
|
||||
}
|
||||
|
||||
return member_functions;
|
||||
}
|
||||
|
||||
static MemberFunctionInfo check_member_function(
|
||||
const std::string& mangled_name,
|
||||
std::string_view type_name_no_template_args,
|
||||
const DemanglerFunctions& demangler,
|
||||
u32 importer_flags)
|
||||
{
|
||||
MemberFunctionInfo info;
|
||||
|
||||
// Some compiler versions output gcc opnames for overloaded operators
|
||||
// instead of their proper names.
|
||||
if((importer_flags & DONT_DEMANGLE_NAMES) == 0 && demangler.cplus_demangle_opname) {
|
||||
char* demangled_name = demangler.cplus_demangle_opname(mangled_name.c_str(), 0);
|
||||
if(demangled_name) {
|
||||
info.name = demangled_name;
|
||||
free(reinterpret_cast<void*>(demangled_name));
|
||||
}
|
||||
}
|
||||
if(info.name.empty()) {
|
||||
info.name = mangled_name;
|
||||
}
|
||||
|
||||
bool is_constructor =
|
||||
info.name == "__ct" || // Takes a parameter to decide whether or not to construct virtual base classes.
|
||||
info.name == "__comp_ctor" || // Constructs virtual base classes.
|
||||
info.name == "__base_ctor"; // Does not construct virtual base classes.
|
||||
|
||||
if(!is_constructor && !type_name_no_template_args.empty()) {
|
||||
is_constructor |= info.name == type_name_no_template_args; // Named constructor.
|
||||
}
|
||||
|
||||
bool is_destructor =
|
||||
info.name == "__dt" || // Takes parameters to decide whether or not to construct virtual base classes and/or delete the object.
|
||||
info.name == "__comp_dtor" || // Destructs virtual base classes.
|
||||
info.name == "__base_dtor" || // Does not construct virtual base classes.
|
||||
info.name == "__deleting_dtor"; // Destructs virtual base clases then deletes the entire object.
|
||||
|
||||
if(!is_destructor && !info.name.empty()) {
|
||||
is_destructor |= info.name[0] == '~' && std::string_view(info.name).substr(1) == type_name_no_template_args; // Named destructor.
|
||||
}
|
||||
|
||||
info.is_constructor_or_destructor = is_constructor || is_destructor || info.name.starts_with("$_");
|
||||
info.is_special_member_function = info.is_constructor_or_destructor || info.name == "operator=";
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void fix_recursively_emitted_structures(
|
||||
ast::StructOrUnion& outer_struct, const std::string& name, StabsTypeNumber type_number, SourceFileHandle file_handle)
|
||||
{
|
||||
// This is a rather peculiar case. For some compiler versions, when a struct
|
||||
// or a union defined using a typedef is being emitted and it needs to
|
||||
// reference itself from a member function parameter, it will emit its
|
||||
// entire definition again in the middle of the first definition, although
|
||||
// thankfully it won't recurse more than once.
|
||||
//
|
||||
// The game Sega Soccer Slam is affected by this. See the PeculiarParameter
|
||||
// test case in mdebug_importer_tests.cpp for a bare bones example.
|
||||
|
||||
for(std::unique_ptr<ast::Node>& node : outer_struct.member_functions) {
|
||||
if(node->descriptor != ast::FUNCTION) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ast::Function& function = node->as<ast::Function>();
|
||||
if(!function.parameters.has_value()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for(std::unique_ptr<ast::Node>& parameter : *function.parameters) {
|
||||
if(parameter->descriptor != ast::POINTER_OR_REFERENCE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ast::PointerOrReference& pointer_or_reference = parameter->as<ast::PointerOrReference>();
|
||||
if(pointer_or_reference.value_type->descriptor != ast::STRUCT_OR_UNION) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ast::StructOrUnion& inner_struct = pointer_or_reference.value_type->as<ast::StructOrUnion>();
|
||||
|
||||
// Since C++ doesn't allow struct definitions in function parameter
|
||||
// lists normally, and most of the time the member function
|
||||
// parameters aren't even filled in by GCC, this is a really rare
|
||||
// case, so here we only bother to do some very basic checks to
|
||||
// verify that the inner struct is similar to the outer struct.
|
||||
if(inner_struct.base_classes.size() != outer_struct.base_classes.size()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(inner_struct.fields.size() != outer_struct.fields.size()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(inner_struct.member_functions.size() != outer_struct.member_functions.size()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto type_name = std::make_unique<ast::TypeName>();
|
||||
type_name->source = ast::TypeNameSource::REFERENCE;
|
||||
type_name->unresolved_stabs = std::make_unique<ast::TypeName::UnresolvedStabs>();
|
||||
type_name->unresolved_stabs->type_name = name;
|
||||
type_name->unresolved_stabs->referenced_file_handle = file_handle;
|
||||
type_name->unresolved_stabs->stabs_type_number = type_number;
|
||||
pointer_or_reference.value_type = std::move(type_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast::AccessSpecifier stabs_field_visibility_to_access_specifier(StabsStructOrUnionType::Visibility visibility)
|
||||
{
|
||||
ast::AccessSpecifier access_specifier = ast::AS_PUBLIC;
|
||||
switch(visibility) {
|
||||
case StabsStructOrUnionType::Visibility::NONE: access_specifier = ast::AS_PUBLIC; break;
|
||||
case StabsStructOrUnionType::Visibility::PUBLIC: access_specifier = ast::AS_PUBLIC; break;
|
||||
case StabsStructOrUnionType::Visibility::PROTECTED: access_specifier = ast::AS_PROTECTED; break;
|
||||
case StabsStructOrUnionType::Visibility::PRIVATE: access_specifier = ast::AS_PRIVATE; break;
|
||||
case StabsStructOrUnionType::Visibility::PUBLIC_OPTIMIZED_OUT: access_specifier = ast::AS_PUBLIC; break;
|
||||
}
|
||||
return access_specifier;
|
||||
}
|
||||
|
||||
}
|
||||
29
3rdparty/ccc/src/ccc/stabs_to_ast.h
vendored
Normal file
29
3rdparty/ccc/src/ccc/stabs_to_ast.h
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ast.h"
|
||||
#include "stabs.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
struct StabsToAstState {
|
||||
u32 file_handle;
|
||||
std::map<StabsTypeNumber, const StabsType*>* stabs_types;
|
||||
u32 importer_flags;
|
||||
DemanglerFunctions demangler;
|
||||
};
|
||||
|
||||
Result<std::unique_ptr<ast::Node>> stabs_type_to_ast(
|
||||
const StabsType& type,
|
||||
const StabsType* enclosing_struct,
|
||||
const StabsToAstState& state,
|
||||
s32 depth,
|
||||
bool substitute_type_name,
|
||||
bool force_substitute);
|
||||
void fix_recursively_emitted_structures(
|
||||
ast::StructOrUnion& outer_struct, const std::string& name, StabsTypeNumber type_number, SourceFileHandle file_handle);
|
||||
ast::AccessSpecifier stabs_field_visibility_to_access_specifier(StabsStructOrUnionType::Visibility visibility);
|
||||
|
||||
}
|
||||
1204
3rdparty/ccc/src/ccc/symbol_database.cpp
vendored
Normal file
1204
3rdparty/ccc/src/ccc/symbol_database.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
721
3rdparty/ccc/src/ccc/symbol_database.h
vendored
Normal file
721
3rdparty/ccc/src/ccc/symbol_database.h
vendored
Normal file
@@ -0,0 +1,721 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <atomic>
|
||||
#include <variant>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
// An X macro for all the symbol types.
|
||||
#define CCC_FOR_EACH_SYMBOL_TYPE_DO_X \
|
||||
CCC_X(DataType, data_types) \
|
||||
CCC_X(Function, functions) \
|
||||
CCC_X(GlobalVariable, global_variables) \
|
||||
CCC_X(Label, labels) \
|
||||
CCC_X(LocalVariable, local_variables) \
|
||||
CCC_X(Module, modules) \
|
||||
CCC_X(ParameterVariable, parameter_variables) \
|
||||
CCC_X(Section, sections) \
|
||||
CCC_X(SourceFile, source_files) \
|
||||
CCC_X(SymbolSource, symbol_sources)
|
||||
|
||||
// An enum for all the symbol types.
|
||||
enum SymbolDescriptor {
|
||||
DATA_TYPE = 1 << 0,
|
||||
FUNCTION = 1 << 1,
|
||||
GLOBAL_VARIABLE = 1 << 2,
|
||||
LABEL = 1 << 3,
|
||||
LOCAL_VARIABLE = 1 << 4,
|
||||
MODULE = 1 << 5,
|
||||
PARAMETER_VARIABLE = 1 << 6,
|
||||
SECTION = 1 << 7,
|
||||
SOURCE_FILE = 1 << 8,
|
||||
SYMBOL_SOURCE = 1 << 9
|
||||
};
|
||||
|
||||
enum {
|
||||
ALL_SYMBOL_TYPES = 0xffff
|
||||
};
|
||||
|
||||
// Forward declare all the different types of symbol objects.
|
||||
#define CCC_X(SymbolType, symbol_list) class SymbolType;
|
||||
CCC_FOR_EACH_SYMBOL_TYPE_DO_X
|
||||
#undef CCC_X
|
||||
|
||||
class SymbolDatabase;
|
||||
|
||||
// Strongly typed handles for all of the symbol objects. These are here to solve
|
||||
// the problem of dangling references to symbols.
|
||||
template <typename SymbolType>
|
||||
struct SymbolHandle {
|
||||
u32 value = (u32) -1;
|
||||
|
||||
SymbolHandle() {}
|
||||
SymbolHandle(u32 v) : value(v) {}
|
||||
SymbolHandle(const SymbolType* symbol)
|
||||
: value(symbol ? symbol->handle().value : (u32) -1) {}
|
||||
|
||||
// Check if this symbol handle has been initialised. Note that this doesn't
|
||||
// determine whether or not the symbol it points to has been deleted!
|
||||
bool valid() const { return value != (u32) -1; }
|
||||
|
||||
friend auto operator<=>(const SymbolHandle& lhs, const SymbolHandle& rhs) = default;
|
||||
};
|
||||
|
||||
#define CCC_X(SymbolType, symbol_list) using SymbolType##Handle = SymbolHandle<SymbolType>;
|
||||
CCC_FOR_EACH_SYMBOL_TYPE_DO_X
|
||||
#undef CCC_X
|
||||
|
||||
enum SymbolFlag {
|
||||
NO_SYMBOL_FLAGS = 0,
|
||||
WITH_ADDRESS_MAP = 1 << 0,
|
||||
WITH_NAME_MAP = 1 << 1,
|
||||
NAME_NEEDS_DEMANGLING = 1 << 2
|
||||
};
|
||||
|
||||
// A container class for symbols of a given type that maintains maps of their
|
||||
// names and addresses depending on the value of SymbolType::FLAGS.
|
||||
template <typename SymbolType>
|
||||
class SymbolList {
|
||||
public:
|
||||
// Lookup symbols from their handles using binary search.
|
||||
SymbolType* symbol_from_handle(SymbolHandle<SymbolType> handle);
|
||||
const SymbolType* symbol_from_handle(SymbolHandle<SymbolType> handle) const;
|
||||
|
||||
// Lookup multiple symbols from their handles using binary search.
|
||||
std::vector<SymbolType*> symbols_from_handles(const std::vector<SymbolHandle<SymbolType>>& handles);
|
||||
std::vector<const SymbolType*> symbols_from_handles(const std::vector<SymbolHandle<SymbolType>>& handles) const;
|
||||
std::vector<SymbolType*> optional_symbols_from_handles(const std::optional<std::vector<SymbolHandle<SymbolType>>>& handles);
|
||||
std::vector<const SymbolType*> optional_symbols_from_handles(const std::optional<std::vector<SymbolHandle<SymbolType>>>& handles) const;
|
||||
|
||||
using Iterator = typename std::vector<SymbolType>::iterator;
|
||||
using ConstIterator = typename std::vector<SymbolType>::const_iterator;
|
||||
|
||||
// For iterating over all the symbols.
|
||||
Iterator begin();
|
||||
ConstIterator begin() const;
|
||||
Iterator end();
|
||||
ConstIterator end() const;
|
||||
|
||||
using AddressToHandleMap = std::multimap<u32, SymbolHandle<SymbolType>>;
|
||||
using NameToHandleMap = std::multimap<std::string, SymbolHandle<SymbolType>>;
|
||||
|
||||
template <typename Iterator>
|
||||
class Iterators {
|
||||
public:
|
||||
Iterators(Iterator b, Iterator e)
|
||||
: m_begin(b), m_end(e) {}
|
||||
Iterator begin() const { return m_begin; }
|
||||
Iterator end() const { return m_end; }
|
||||
protected:
|
||||
Iterator m_begin;
|
||||
Iterator m_end;
|
||||
};
|
||||
|
||||
using AddressToHandleMapIterators = Iterators<typename AddressToHandleMap::const_iterator>;
|
||||
using NameToHandleMapIterators = Iterators<typename NameToHandleMap::const_iterator>;
|
||||
|
||||
// Lookup symbols by their address.
|
||||
AddressToHandleMapIterators handles_from_starting_address(Address address) const;
|
||||
AddressToHandleMapIterators handles_from_address_range(AddressRange range) const;
|
||||
SymbolHandle<SymbolType> first_handle_from_starting_address(Address address) const;
|
||||
SymbolHandle<SymbolType> first_handle_after_address(Address address) const;
|
||||
|
||||
// Lookup symbols by their name.
|
||||
NameToHandleMapIterators handles_from_name(const std::string& name) const;
|
||||
SymbolHandle<SymbolType> first_handle_from_name(const std::string& name) const;
|
||||
|
||||
// Find a symbol with an address range that contains the provided address.
|
||||
// For example, to find which function an instruction belongs to.
|
||||
SymbolType* symbol_overlapping_address(Address address);
|
||||
const SymbolType* symbol_overlapping_address(Address address) const;
|
||||
|
||||
// Convert handles to underlying array indices.
|
||||
s32 index_from_handle(SymbolHandle<SymbolType> handle) const;
|
||||
|
||||
// Index into the underlying array.
|
||||
SymbolType& symbol_from_index(s32 index);
|
||||
const SymbolType& symbol_from_index(s32 index) const;
|
||||
|
||||
// Determine if any symbols are being stored.
|
||||
bool empty() const;
|
||||
|
||||
// Retrieve the number of symbols stored.
|
||||
s32 size() const;
|
||||
|
||||
// Create a new symbol. If it's a SymbolSource symbol, source can be left
|
||||
// empty, otherwise it has to be valid.
|
||||
Result<SymbolType*> create_symbol(
|
||||
std::string name, Address address, SymbolSourceHandle source, const Module* module_symbol = nullptr);
|
||||
|
||||
// Create a new symbol. Similar to above, but for symbols without addresses.
|
||||
Result<SymbolType*> create_symbol(
|
||||
std::string name, SymbolSourceHandle source, const Module* module_symbol = nullptr);
|
||||
|
||||
// Create a new symbol. Similar to above, but unless DONT_DEMANGLE_NAMES is
|
||||
// set, the name of the symbol will be demangled.
|
||||
Result<SymbolType*> create_symbol(
|
||||
std::string name,
|
||||
SymbolSourceHandle source,
|
||||
const Module* module_symbol,
|
||||
Address address,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler);
|
||||
|
||||
// Update the address of a symbol without changing its handle.
|
||||
bool move_symbol(SymbolHandle<SymbolType> handle, Address new_address);
|
||||
|
||||
// Update the name of a symbol without changing its handle.
|
||||
bool rename_symbol(SymbolHandle<SymbolType> handle, std::string new_name);
|
||||
|
||||
// Move all the symbols from the passed list into this list.
|
||||
void merge_from(SymbolList<SymbolType>& list);
|
||||
|
||||
// Mark a symbol for destruction. If the correct symbol database pointer is
|
||||
// passed, all descendants will also be marked. For example, marking a
|
||||
// function will also mark its parameters and local variables.
|
||||
bool mark_symbol_for_destruction(SymbolHandle<SymbolType> handle, SymbolDatabase* database);
|
||||
|
||||
// Mark all the symbols from a given symbol source for destruction. For
|
||||
// example you can use this to free a symbol table without destroying
|
||||
// user-defined symbols. The behaviour for marking descendants is the same
|
||||
// as destroy_symbol.
|
||||
void mark_symbols_from_source_for_destruction(SymbolSourceHandle source, SymbolDatabase* database);
|
||||
|
||||
// Mark all the symbols from a given module for destruction. The behaviour
|
||||
// for marking descendants is the same as destroy_symbol.
|
||||
void mark_symbols_from_module_for_destruction(ModuleHandle module_handle, SymbolDatabase* database);
|
||||
|
||||
// Destroy all symbols that have previously been marked for destruction.
|
||||
// This invalidates all pointers to symbols in this list.
|
||||
void destroy_marked_symbols();
|
||||
|
||||
// Destroy all symbols, but don't reset m_next_handle so we don't have to
|
||||
// worry about dangling handles.
|
||||
void clear();
|
||||
|
||||
protected:
|
||||
// Do a binary search for a handle, and return either its index, or the
|
||||
// index where it could be inserted.
|
||||
size_t binary_search(SymbolHandle<SymbolType> handle) const;
|
||||
|
||||
// Keep the address map in sync with the symbol list.
|
||||
void link_address_map(SymbolType& symbol);
|
||||
void unlink_address_map(SymbolType& symbol);
|
||||
|
||||
// Keep the name map in sync with the symbol list.
|
||||
void link_name_map(SymbolType& symbol);
|
||||
void unlink_name_map(SymbolType& symbol);
|
||||
|
||||
std::vector<SymbolType> m_symbols;
|
||||
AddressToHandleMap m_address_to_handle;
|
||||
NameToHandleMap m_name_to_handle;
|
||||
|
||||
// We share this between symbol lists of the same type so that we can merge
|
||||
// them without having to rewrite all the handles.
|
||||
static std::atomic<u32> m_next_handle;
|
||||
};
|
||||
|
||||
// Base class for all the symbols.
|
||||
class Symbol {
|
||||
template <typename SymbolType>
|
||||
friend class SymbolList;
|
||||
public:
|
||||
const std::string& name() const { return m_name; }
|
||||
u32 raw_handle() const { return m_handle; }
|
||||
SymbolSourceHandle source() const { return m_source; }
|
||||
ModuleHandle module_handle() const { return m_module; }
|
||||
|
||||
Address address() const { return m_address; }
|
||||
u32 size() const { return m_size; }
|
||||
void set_size(u32 size) { m_size = size; }
|
||||
AddressRange address_range() const { return AddressRange(m_address, m_address.get_or_zero() + m_size); }
|
||||
|
||||
ast::Node* type() { return m_type.get(); }
|
||||
const ast::Node* type() const { return m_type.get(); }
|
||||
void set_type(std::unique_ptr<ast::Node> type);
|
||||
|
||||
u32 generation() const { return m_generation; }
|
||||
|
||||
// This MUST be called after any AST nodes have been created/deleted/moved.
|
||||
// For the set_type function this is done for you.
|
||||
void invalidate_node_handles() { m_generation++; }
|
||||
|
||||
// Mark a single symbol for destruction, not including its descendants.
|
||||
void mark_for_destruction() { m_marked_for_destruction = true; }
|
||||
bool is_marked_for_destruction() { return m_marked_for_destruction; }
|
||||
|
||||
protected:
|
||||
void on_create() {}
|
||||
void on_destroy(SymbolDatabase* database) {}
|
||||
|
||||
u32 m_handle = (u32) -1;
|
||||
SymbolSourceHandle m_source;
|
||||
Address m_address;
|
||||
u32 m_size = 0;
|
||||
std::string m_name;
|
||||
std::unique_ptr<ast::Node> m_type;
|
||||
u32 m_generation : 31 = 0;
|
||||
u32 m_marked_for_destruction : 1 = false;
|
||||
ModuleHandle m_module;
|
||||
};
|
||||
|
||||
// Variable storage types. This is different to whether the variable is a
|
||||
// global, local or parameter. For example local variables can have global
|
||||
// storage (static locals).
|
||||
|
||||
enum GlobalStorageLocation {
|
||||
NIL,
|
||||
DATA,
|
||||
BSS,
|
||||
ABS,
|
||||
SDATA,
|
||||
SBSS,
|
||||
RDATA,
|
||||
COMMON,
|
||||
SCOMMON,
|
||||
SUNDEFINED
|
||||
};
|
||||
|
||||
const char* global_storage_location_to_string(GlobalStorageLocation location);
|
||||
|
||||
struct GlobalStorage {
|
||||
GlobalStorageLocation location = GlobalStorageLocation::NIL;
|
||||
|
||||
GlobalStorage() {}
|
||||
friend auto operator<=>(const GlobalStorage& lhs, const GlobalStorage& rhs) = default;
|
||||
};
|
||||
|
||||
struct RegisterStorage {
|
||||
s32 dbx_register_number = -1;
|
||||
bool is_by_reference;
|
||||
|
||||
RegisterStorage() {}
|
||||
friend auto operator<=>(const RegisterStorage& lhs, const RegisterStorage& rhs) = default;
|
||||
};
|
||||
|
||||
struct StackStorage {
|
||||
s32 stack_pointer_offset = -1;
|
||||
|
||||
StackStorage() {}
|
||||
friend auto operator<=>(const StackStorage& lhs, const StackStorage& rhs) = default;
|
||||
};
|
||||
|
||||
// The hashing algorithm for functions. If you change this algorithm make sure
|
||||
// to bump the version number for the JSON format so we can know if a hash was
|
||||
// generated using the new algorithm or not.
|
||||
class FunctionHash {
|
||||
public:
|
||||
void update(u32 instruction)
|
||||
{
|
||||
// Separate out the opcode so that the hash remains the same regardless
|
||||
// of if relocations are applied or not.
|
||||
u32 opcode = instruction >> 26;
|
||||
m_hash = m_hash * 31 + opcode;
|
||||
}
|
||||
|
||||
u32 get() const
|
||||
{
|
||||
return m_hash;
|
||||
}
|
||||
|
||||
protected:
|
||||
u32 m_hash = 0;
|
||||
};
|
||||
|
||||
// All the different types of symbol objects.
|
||||
|
||||
// A C/C++ data type.
|
||||
class DataType : public Symbol {
|
||||
friend SourceFile;
|
||||
public:
|
||||
static constexpr const SymbolDescriptor DESCRIPTOR = DATA_TYPE;
|
||||
static constexpr const char* NAME = "Data Type";
|
||||
static constexpr const u32 FLAGS = WITH_NAME_MAP;
|
||||
|
||||
DataTypeHandle handle() const { return m_handle; }
|
||||
|
||||
std::vector<SourceFileHandle> files; // List of files for which a given top-level type is present.
|
||||
const char* compare_fail_reason = nullptr;
|
||||
|
||||
bool not_defined_in_any_translation_unit : 1 = false;
|
||||
bool only_defined_in_single_translation_unit : 1 = false;
|
||||
};
|
||||
|
||||
// A function. The type stored is the return type.
|
||||
class Function : public Symbol {
|
||||
friend SourceFile;
|
||||
friend SymbolList<Function>;
|
||||
public:
|
||||
static constexpr const SymbolDescriptor DESCRIPTOR = FUNCTION;
|
||||
static constexpr const char* NAME = "Function";
|
||||
static constexpr const u32 FLAGS = WITH_ADDRESS_MAP | WITH_NAME_MAP | NAME_NEEDS_DEMANGLING;
|
||||
|
||||
FunctionHandle handle() const { return m_handle; }
|
||||
SourceFileHandle source_file() const { return m_source_file; }
|
||||
|
||||
const std::optional<std::vector<ParameterVariableHandle>>& parameter_variables() const;
|
||||
void set_parameter_variables(std::optional<std::vector<ParameterVariableHandle>> parameter_variables, SymbolDatabase& database);
|
||||
|
||||
const std::optional<std::vector<LocalVariableHandle>>& local_variables() const;
|
||||
void set_local_variables(std::optional<std::vector<LocalVariableHandle>> local_variables, SymbolDatabase& database);
|
||||
|
||||
const std::string& mangled_name() const;
|
||||
void set_mangled_name(std::string mangled);
|
||||
|
||||
// A hash of all the opcodes in the function, read from file.
|
||||
u32 original_hash() const;
|
||||
void set_original_hash(u32 hash);
|
||||
|
||||
// A hash of all the opcodes in the function, read from memory.
|
||||
u32 current_hash() const;
|
||||
void set_current_hash(FunctionHash hash);
|
||||
|
||||
struct LineNumberPair {
|
||||
Address address;
|
||||
s32 line_number;
|
||||
};
|
||||
|
||||
struct SubSourceFile {
|
||||
Address address;
|
||||
std::string relative_path;
|
||||
};
|
||||
|
||||
std::string relative_path;
|
||||
StorageClass storage_class;
|
||||
s32 stack_frame_size = -1;
|
||||
std::vector<LineNumberPair> line_numbers;
|
||||
std::vector<SubSourceFile> sub_source_files;
|
||||
bool is_member_function_ish = false; // Filled in by fill_in_pointers_to_member_function_definitions.
|
||||
bool is_no_return = false;
|
||||
|
||||
protected:
|
||||
void on_destroy(SymbolDatabase* database);
|
||||
|
||||
SourceFileHandle m_source_file;
|
||||
std::optional<std::vector<ParameterVariableHandle>> m_parameter_variables;
|
||||
std::optional<std::vector<LocalVariableHandle>> m_local_variables;
|
||||
|
||||
std::string m_mangled_name;
|
||||
|
||||
u32 m_original_hash = 0;
|
||||
u32 m_current_hash = 0;
|
||||
};
|
||||
|
||||
// A global variable.
|
||||
class GlobalVariable : public Symbol {
|
||||
friend SourceFile;
|
||||
public:
|
||||
static constexpr const SymbolDescriptor DESCRIPTOR = GLOBAL_VARIABLE;
|
||||
static constexpr const char* NAME = "Global Variable";
|
||||
static constexpr u32 FLAGS = WITH_ADDRESS_MAP | WITH_NAME_MAP | NAME_NEEDS_DEMANGLING;
|
||||
|
||||
GlobalVariableHandle handle() const { return m_handle; }
|
||||
SourceFileHandle source_file() const { return m_source_file; };
|
||||
|
||||
const std::string& mangled_name() const;
|
||||
void set_mangled_name(std::string mangled);
|
||||
|
||||
GlobalStorage storage;
|
||||
StorageClass storage_class;
|
||||
|
||||
protected:
|
||||
SourceFileHandle m_source_file;
|
||||
std::string m_mangled_name;
|
||||
};
|
||||
|
||||
// A label. This could be a label defined in assembly, C/C++, or just a symbol
|
||||
// that we can't automatically determine the type of (e.g. SNDLL symbols).
|
||||
class Label : public Symbol {
|
||||
public:
|
||||
static constexpr const SymbolDescriptor DESCRIPTOR = LABEL;
|
||||
static constexpr const char* NAME = "Label";
|
||||
static constexpr u32 FLAGS = WITH_ADDRESS_MAP | WITH_NAME_MAP;
|
||||
|
||||
LabelHandle handle() const { return m_handle; }
|
||||
|
||||
// Indicates that this label should not be used as a function name.
|
||||
bool is_junk = false;
|
||||
};
|
||||
|
||||
// A local variable. This includes static local variables which have global
|
||||
// storage.
|
||||
class LocalVariable : public Symbol {
|
||||
friend Function;
|
||||
public:
|
||||
static constexpr const SymbolDescriptor DESCRIPTOR = LOCAL_VARIABLE;
|
||||
static constexpr const char* NAME = "Local Variable";
|
||||
static constexpr u32 FLAGS = WITH_ADDRESS_MAP;
|
||||
|
||||
LocalVariableHandle handle() const { return m_handle; }
|
||||
FunctionHandle function() const { return m_function; };
|
||||
|
||||
std::variant<GlobalStorage, RegisterStorage, StackStorage> storage;
|
||||
AddressRange live_range;
|
||||
|
||||
protected:
|
||||
FunctionHandle m_function;
|
||||
};
|
||||
|
||||
// A program module e.g. an ELF file or an SNDLL file. Every symbol has a module
|
||||
// field indicating what module the symbol belongs to. This can be used to
|
||||
// delete all the symbols associated with a given module. Additionally, when a
|
||||
// valid module pointer is passed to SymbolList<>::create_symbol, the address of
|
||||
// the symbol will be added to the address of the new symbol.
|
||||
class Module : public Symbol {
|
||||
friend SymbolList<Module>;
|
||||
public:
|
||||
static constexpr const SymbolDescriptor DESCRIPTOR = MODULE;
|
||||
static constexpr const char* NAME = "Module";
|
||||
static constexpr u32 FLAGS = WITH_NAME_MAP;
|
||||
|
||||
ModuleHandle handle() const { return m_handle; }
|
||||
|
||||
// These are used for IRX modules.
|
||||
bool is_irx = false;
|
||||
s32 version_major = -1;
|
||||
s32 version_minor = -1;
|
||||
|
||||
protected:
|
||||
void on_create();
|
||||
};
|
||||
|
||||
// A parameter variable.
|
||||
class ParameterVariable : public Symbol {
|
||||
friend Function;
|
||||
public:
|
||||
static constexpr const SymbolDescriptor DESCRIPTOR = PARAMETER_VARIABLE;
|
||||
static constexpr const char* NAME = "Parameter Variable";
|
||||
static constexpr u32 FLAGS = NO_SYMBOL_FLAGS;
|
||||
|
||||
ParameterVariableHandle handle() const { return m_handle; }
|
||||
FunctionHandle function() const { return m_function; };
|
||||
|
||||
std::variant<RegisterStorage, StackStorage> storage;
|
||||
|
||||
protected:
|
||||
FunctionHandle m_function;
|
||||
};
|
||||
|
||||
// An ELF section. These are created from the ELF section headers.
|
||||
class Section : public Symbol {
|
||||
public:
|
||||
static constexpr const SymbolDescriptor DESCRIPTOR = SECTION;
|
||||
static constexpr const char* NAME = "Section";
|
||||
static constexpr u32 FLAGS = WITH_ADDRESS_MAP | WITH_NAME_MAP;
|
||||
|
||||
SectionHandle handle() const { return m_handle; }
|
||||
|
||||
// Check if the section name is ".text".
|
||||
bool contains_code() const;
|
||||
|
||||
// Check for known data section names.
|
||||
bool contains_data() const;
|
||||
};
|
||||
|
||||
// A source file (.c or .cpp file). One of these will be created for every
|
||||
// translation unit in the program (but only if debugging symbols are present).
|
||||
class SourceFile : public Symbol {
|
||||
friend SymbolList<SourceFile>;
|
||||
public:
|
||||
static constexpr const SymbolDescriptor DESCRIPTOR = SOURCE_FILE;
|
||||
static constexpr const char* NAME = "Source File";
|
||||
static constexpr u32 FLAGS = WITH_ADDRESS_MAP | WITH_NAME_MAP;
|
||||
|
||||
SourceFileHandle handle() const { return m_handle; }
|
||||
const std::string& full_path() const { return name(); }
|
||||
|
||||
const std::vector<FunctionHandle>& functions() const;
|
||||
void set_functions(std::vector<FunctionHandle> functions, SymbolDatabase& database);
|
||||
|
||||
const std::vector<GlobalVariableHandle>& global_variables() const;
|
||||
void set_global_variables(std::vector<GlobalVariableHandle> global_variables, SymbolDatabase& database);
|
||||
|
||||
// Check whether at least half of the functions associated with the source
|
||||
// file match their original hash (meaning they haven't been overwritten).
|
||||
bool functions_match() const;
|
||||
void check_functions_match(const SymbolDatabase& database);
|
||||
|
||||
std::string working_dir;
|
||||
std::string command_line_path;
|
||||
std::map<StabsTypeNumber, DataTypeHandle> stabs_type_number_to_handle;
|
||||
std::set<std::string> toolchain_version_info;
|
||||
|
||||
protected:
|
||||
void on_destroy(SymbolDatabase* database);
|
||||
|
||||
std::vector<FunctionHandle> m_functions;
|
||||
std::vector<GlobalVariableHandle> m_global_variables;
|
||||
bool m_functions_match = true;
|
||||
};
|
||||
|
||||
// A symbol source. Every symbol has a symbol source field indicating how the
|
||||
// symbol was created. For example, the symbol table importers will each create
|
||||
// one of these (if it doesn't already exist).
|
||||
class SymbolSource : public Symbol {
|
||||
friend SymbolList<SymbolSource>;
|
||||
public:
|
||||
static constexpr const SymbolDescriptor DESCRIPTOR = SYMBOL_SOURCE;
|
||||
static constexpr const char* NAME = "Symbol Source";
|
||||
static constexpr u32 FLAGS = WITH_NAME_MAP;
|
||||
|
||||
SymbolSourceHandle handle() const { return m_handle; }
|
||||
|
||||
protected:
|
||||
void on_create();
|
||||
};
|
||||
|
||||
// Bundles together all the information needed to identify if a symbol came from
|
||||
// a specific symbol table import operation. For example, this is used to make
|
||||
// sure that we don't reference symbols from another symbol table during the
|
||||
// import process.
|
||||
struct SymbolGroup {
|
||||
SymbolSourceHandle source;
|
||||
Module* module_symbol = nullptr;
|
||||
|
||||
bool is_in_group(const Symbol& symbol) const;
|
||||
};
|
||||
|
||||
// The symbol database itself. This owns all the symbols.
|
||||
class SymbolDatabase {
|
||||
public:
|
||||
SymbolList<DataType> data_types;
|
||||
SymbolList<Function> functions;
|
||||
SymbolList<GlobalVariable> global_variables;
|
||||
SymbolList<Label> labels;
|
||||
SymbolList<LocalVariable> local_variables;
|
||||
SymbolList<Module> modules;
|
||||
SymbolList<ParameterVariable> parameter_variables;
|
||||
SymbolList<Section> sections;
|
||||
SymbolList<SourceFile> source_files;
|
||||
SymbolList<SymbolSource> symbol_sources;
|
||||
|
||||
// Sum up the symbol counts for each symbol list.
|
||||
s32 symbol_count() const;
|
||||
|
||||
// Find a symbol of any of the specified types given an address. Symbols of
|
||||
// the types specified higher up in the CCC_FOR_EACH_SYMBOL_TYPE_DO_X macro
|
||||
// are checked for first.
|
||||
const Symbol* symbol_starting_at_address(
|
||||
Address address, u32 descriptors = ALL_SYMBOL_TYPES, SymbolDescriptor* descriptor_out = nullptr) const;
|
||||
const Symbol* symbol_after_address(
|
||||
Address address, u32 descriptors = ALL_SYMBOL_TYPES, SymbolDescriptor* descriptor_out = nullptr) const;
|
||||
const Symbol* symbol_overlapping_address(
|
||||
Address address, u32 descriptors = ALL_SYMBOL_TYPES, SymbolDescriptor* descriptor_out = nullptr) const;
|
||||
|
||||
// Find a symbol of any of the specified types given its name. Symbols of
|
||||
// the types specified higher up in the CCC_FOR_EACH_SYMBOL_TYPE_DO_X macro
|
||||
// are checked for first.
|
||||
const Symbol* symbol_with_name(
|
||||
const std::string& name, u32 descriptors = ALL_SYMBOL_TYPES, SymbolDescriptor* descriptor_out = nullptr) const;
|
||||
|
||||
// Finds a symbol source object with the given name or creates one if it
|
||||
// doesn't already exist.
|
||||
Result<SymbolSourceHandle> get_symbol_source(const std::string& name);
|
||||
|
||||
// Deduplicate matching data types with the same name. May replace the
|
||||
// existing data type with the new one if the new one is better.
|
||||
Result<DataType*> create_data_type_if_unique(
|
||||
std::unique_ptr<ast::Node> node,
|
||||
StabsTypeNumber number,
|
||||
const char* name,
|
||||
SourceFile& source_file,
|
||||
const SymbolGroup& group);
|
||||
|
||||
// Move all the symbols in the passed database into this database.
|
||||
void merge_from(SymbolDatabase& database);
|
||||
|
||||
// Destroy all the symbols from a given symbol source. For example you can
|
||||
// use this to free a symbol table without destroying user-defined symbols.
|
||||
void destroy_symbols_from_source(SymbolSourceHandle source, bool destroy_descendants);
|
||||
|
||||
// Destroy all the symbols from a given module.
|
||||
void destroy_symbols_from_module(ModuleHandle module_handle, bool destroy_descendants);
|
||||
|
||||
// Destroy all the symbols that have previously been marked for destruction.
|
||||
// This invalidates all pointers to symbols in this database.
|
||||
void destroy_marked_symbols();
|
||||
|
||||
// Destroy all the symbols in the symbol database.
|
||||
void clear();
|
||||
|
||||
template <typename Callback>
|
||||
void for_each_symbol(Callback callback) {
|
||||
// Use indices here to avoid iterator invalidation.
|
||||
#define CCC_X(SymbolType, symbol_list) \
|
||||
for(s32 i = 0; i < symbol_list.size(); i++) { \
|
||||
callback(symbol_list.symbol_from_index(i)); \
|
||||
}
|
||||
CCC_FOR_EACH_SYMBOL_TYPE_DO_X
|
||||
#undef CCC_X
|
||||
}
|
||||
};
|
||||
|
||||
// A handle to a symbol of any type.
|
||||
class MultiSymbolHandle {
|
||||
public:
|
||||
// Create an empty multi symbol handle.
|
||||
MultiSymbolHandle();
|
||||
|
||||
// Create a multi symbol handle of the specified type.
|
||||
template <typename SymbolType>
|
||||
MultiSymbolHandle(const SymbolType& symbol);
|
||||
MultiSymbolHandle(SymbolDescriptor descriptor, u32 handle);
|
||||
|
||||
bool valid() const;
|
||||
SymbolDescriptor descriptor() const;
|
||||
u32 handle() const;
|
||||
|
||||
Symbol* lookup_symbol(SymbolDatabase& database);
|
||||
const Symbol* lookup_symbol(const SymbolDatabase& database) const;
|
||||
|
||||
bool is_flag_set(SymbolFlag flag) const;
|
||||
bool move_symbol(Address new_address, SymbolDatabase& database) const;
|
||||
bool rename_symbol(std::string new_name, SymbolDatabase& database) const;
|
||||
bool destroy_symbol(SymbolDatabase& database, bool destroy_descendants) const;
|
||||
|
||||
friend auto operator<=>(const MultiSymbolHandle& lhs, const MultiSymbolHandle& rhs) = default;
|
||||
|
||||
protected:
|
||||
SymbolDescriptor m_descriptor = DATA_TYPE;
|
||||
u32 m_handle = (u32) -1;
|
||||
};
|
||||
|
||||
// A handle to an AST node.
|
||||
class NodeHandle {
|
||||
friend SymbolDatabase;
|
||||
public:
|
||||
// Create an empty node handle.
|
||||
NodeHandle();
|
||||
|
||||
// Create a node handle that will always allow accesses to its node. You
|
||||
// should only use this if you know the lifetime of the handle is a subset
|
||||
// of the lifetime of the node.
|
||||
NodeHandle(const ast::Node* node);
|
||||
|
||||
// Create a node handle pointing to an AST node from a given symbol that
|
||||
// will prevent accesses to the node if the symbol is deleted.
|
||||
template <typename SymbolType>
|
||||
NodeHandle(const SymbolType& symbol, const ast::Node* node);
|
||||
NodeHandle(SymbolDescriptor descriptor, const Symbol& symbol, const ast::Node* node);
|
||||
|
||||
bool valid() const;
|
||||
const MultiSymbolHandle& symbol() const;
|
||||
|
||||
const ast::Node* lookup_node(const SymbolDatabase& database) const;
|
||||
NodeHandle handle_for_child(const ast::Node* child_node) const;
|
||||
|
||||
friend auto operator<=>(const NodeHandle& lhs, const NodeHandle& rhs) = default;
|
||||
|
||||
protected:
|
||||
MultiSymbolHandle m_symbol;
|
||||
const ast::Node* m_node = nullptr;
|
||||
u32 m_generation = 0;
|
||||
};
|
||||
|
||||
}
|
||||
114
3rdparty/ccc/src/ccc/symbol_file.cpp
vendored
Normal file
114
3rdparty/ccc/src/ccc/symbol_file.cpp
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "symbol_file.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
Result<std::unique_ptr<SymbolFile>> parse_symbol_file(std::vector<u8> image, std::string file_name)
|
||||
{
|
||||
const std::optional<u32> magic = copy_unaligned<u32>(image, 0);
|
||||
CCC_CHECK(magic.has_value(), "File too small.");
|
||||
|
||||
std::unique_ptr<SymbolFile> symbol_file;
|
||||
|
||||
switch(*magic) {
|
||||
case CCC_FOURCC("\x7f""ELF"): {
|
||||
Result<ElfFile> elf = ElfFile::parse(std::move(image));
|
||||
CCC_RETURN_IF_ERROR(elf);
|
||||
|
||||
symbol_file = std::make_unique<ElfSymbolFile>(std::move(*elf), std::move(file_name));
|
||||
break;
|
||||
}
|
||||
case CCC_FOURCC("SNR1"):
|
||||
case CCC_FOURCC("SNR2"): {
|
||||
Result<SNDLLFile> sndll = parse_sndll_file(image, Address(), SNDLLType::DYNAMIC_LIBRARY);
|
||||
CCC_RETURN_IF_ERROR(sndll);
|
||||
|
||||
symbol_file = std::make_unique<SNDLLSymbolFile>(std::make_shared<SNDLLFile>(std::move(*sndll)));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return CCC_FAILURE("Unknown file type.");
|
||||
}
|
||||
}
|
||||
|
||||
return symbol_file;
|
||||
}
|
||||
|
||||
ElfSymbolFile::ElfSymbolFile(ElfFile elf, std::string elf_name)
|
||||
: m_elf(std::move(elf)), m_name(std::move(elf_name)) {}
|
||||
|
||||
std::string ElfSymbolFile::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
Result<std::vector<std::unique_ptr<SymbolTable>>> ElfSymbolFile::get_all_symbol_tables() const
|
||||
{
|
||||
std::vector<std::unique_ptr<SymbolTable>> symbol_tables;
|
||||
|
||||
symbol_tables.emplace_back(std::make_unique<ElfSectionHeadersSymbolTable>(m_elf));
|
||||
|
||||
for(size_t i = 0; i < SYMBOL_TABLE_FORMATS.size(); i++) {
|
||||
const SymbolTableFormatInfo& info = SYMBOL_TABLE_FORMATS[i];
|
||||
|
||||
const ElfSection* section = m_elf.lookup_section(info.section_name);
|
||||
if(section) {
|
||||
Result<std::unique_ptr<SymbolTable>> symbol_table = create_elf_symbol_table(*section, m_elf, info.format);
|
||||
CCC_RETURN_IF_ERROR(symbol_table);
|
||||
if(*symbol_table) {
|
||||
symbol_tables.emplace_back(std::move(*symbol_table));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return symbol_tables;
|
||||
}
|
||||
|
||||
Result<std::vector<std::unique_ptr<SymbolTable>>> ElfSymbolFile::get_symbol_tables_from_sections(
|
||||
const std::vector<SymbolTableLocation>& sections) const
|
||||
{
|
||||
std::vector<std::unique_ptr<SymbolTable>> symbol_tables;
|
||||
|
||||
for(const SymbolTableLocation& location : sections) {
|
||||
const ElfSection* section = m_elf.lookup_section(location.section_name.c_str());
|
||||
CCC_CHECK(section, "No '%s' section.", location.section_name.c_str());
|
||||
|
||||
Result<std::unique_ptr<SymbolTable>> symbol_table = create_elf_symbol_table(*section, m_elf, location.format);
|
||||
CCC_RETURN_IF_ERROR(symbol_table);
|
||||
if(*symbol_table) {
|
||||
symbol_tables.emplace_back(std::move(*symbol_table));
|
||||
}
|
||||
}
|
||||
|
||||
return symbol_tables;
|
||||
}
|
||||
|
||||
const ElfFile& ElfSymbolFile::elf() const
|
||||
{
|
||||
return m_elf;
|
||||
}
|
||||
|
||||
SNDLLSymbolFile::SNDLLSymbolFile(std::shared_ptr<SNDLLFile> sndll)
|
||||
: m_sndll(std::move(sndll)) {}
|
||||
|
||||
std::string SNDLLSymbolFile::name() const
|
||||
{
|
||||
return m_sndll->elf_path;
|
||||
}
|
||||
|
||||
Result<std::vector<std::unique_ptr<SymbolTable>>> SNDLLSymbolFile::get_all_symbol_tables() const
|
||||
{
|
||||
std::vector<std::unique_ptr<SymbolTable>> symbol_tables;
|
||||
symbol_tables.emplace_back(std::make_unique<SNDLLSymbolTable>(m_sndll));
|
||||
return symbol_tables;
|
||||
}
|
||||
|
||||
Result<std::vector<std::unique_ptr<SymbolTable>>> SNDLLSymbolFile::get_symbol_tables_from_sections(
|
||||
const std::vector<SymbolTableLocation>& sections) const
|
||||
{
|
||||
return CCC_FAILURE("An SNDLL file is not composed of sections.");
|
||||
}
|
||||
|
||||
}
|
||||
62
3rdparty/ccc/src/ccc/symbol_file.h
vendored
Normal file
62
3rdparty/ccc/src/ccc/symbol_file.h
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "elf.h"
|
||||
#include "sndll.h"
|
||||
#include "symbol_table.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
struct SymbolTableLocation {
|
||||
std::string section_name;
|
||||
SymbolTableFormat format;
|
||||
};
|
||||
|
||||
class SymbolFile {
|
||||
public:
|
||||
virtual ~SymbolFile() {}
|
||||
|
||||
virtual std::string name() const = 0;
|
||||
|
||||
virtual Result<std::vector<std::unique_ptr<SymbolTable>>> get_all_symbol_tables() const = 0;
|
||||
virtual Result<std::vector<std::unique_ptr<SymbolTable>>> get_symbol_tables_from_sections(
|
||||
const std::vector<SymbolTableLocation>& sections) const = 0;
|
||||
};
|
||||
|
||||
// Determine the type of the input file and parse it.
|
||||
Result<std::unique_ptr<SymbolFile>> parse_symbol_file(std::vector<u8> image, std::string file_name);
|
||||
|
||||
class ElfSymbolFile : public SymbolFile {
|
||||
public:
|
||||
ElfSymbolFile(ElfFile elf, std::string elf_name);
|
||||
|
||||
std::string name() const override;
|
||||
|
||||
Result<std::vector<std::unique_ptr<SymbolTable>>> get_all_symbol_tables() const override;
|
||||
Result<std::vector<std::unique_ptr<SymbolTable>>> get_symbol_tables_from_sections(
|
||||
const std::vector<SymbolTableLocation>& sections) const override;
|
||||
|
||||
const ElfFile& elf() const;
|
||||
|
||||
protected:
|
||||
ElfFile m_elf;
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
class SNDLLSymbolFile : public SymbolFile {
|
||||
public:
|
||||
SNDLLSymbolFile(std::shared_ptr<SNDLLFile> sndll);
|
||||
|
||||
std::string name() const override;
|
||||
|
||||
Result<std::vector<std::unique_ptr<SymbolTable>>> get_all_symbol_tables() const override;
|
||||
Result<std::vector<std::unique_ptr<SymbolTable>>> get_symbol_tables_from_sections(
|
||||
const std::vector<SymbolTableLocation>& sections) const override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<SNDLLFile> m_sndll;
|
||||
};
|
||||
|
||||
}
|
||||
285
3rdparty/ccc/src/ccc/symbol_table.cpp
vendored
Normal file
285
3rdparty/ccc/src/ccc/symbol_table.cpp
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "symbol_table.h"
|
||||
|
||||
#include "elf.h"
|
||||
#include "elf_symtab.h"
|
||||
#include "mdebug_importer.h"
|
||||
#include "mdebug_section.h"
|
||||
#include "sndll.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
const std::vector<SymbolTableFormatInfo> SYMBOL_TABLE_FORMATS = {
|
||||
{MDEBUG, "mdebug", ".mdebug"}, // The infamous Third Eye symbol table.
|
||||
{SYMTAB, "symtab", ".symtab"}, // The standard ELF symbol table.
|
||||
{SNDLL, "sndll", ".sndata"} // The SNDLL symbol table.
|
||||
};
|
||||
|
||||
const SymbolTableFormatInfo* symbol_table_format_from_enum(SymbolTableFormat format)
|
||||
{
|
||||
for(size_t i = 0; i < SYMBOL_TABLE_FORMATS.size(); i++) {
|
||||
if(SYMBOL_TABLE_FORMATS[i].format == format) {
|
||||
return &SYMBOL_TABLE_FORMATS[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SymbolTableFormatInfo* symbol_table_format_from_name(const char* format_name)
|
||||
{
|
||||
for(size_t i = 0; i < SYMBOL_TABLE_FORMATS.size(); i++) {
|
||||
if(strcmp(SYMBOL_TABLE_FORMATS[i].format_name, format_name) == 0) {
|
||||
return &SYMBOL_TABLE_FORMATS[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SymbolTableFormatInfo* symbol_table_format_from_section(const char* section_name)
|
||||
{
|
||||
for(size_t i = 0; i < SYMBOL_TABLE_FORMATS.size(); i++) {
|
||||
if(strcmp(SYMBOL_TABLE_FORMATS[i].section_name, section_name) == 0) {
|
||||
return &SYMBOL_TABLE_FORMATS[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
Result<std::unique_ptr<SymbolTable>> create_elf_symbol_table(
|
||||
const ElfSection& section, const ElfFile& elf, SymbolTableFormat format)
|
||||
{
|
||||
std::unique_ptr<SymbolTable> symbol_table;
|
||||
switch(format) {
|
||||
case MDEBUG: {
|
||||
symbol_table = std::make_unique<MdebugSymbolTable>(elf.image, (s32) section.header.offset);
|
||||
break;
|
||||
}
|
||||
case SYMTAB: {
|
||||
CCC_CHECK(section.header.offset + section.header.size <= elf.image.size(),
|
||||
"Section '%s' out of range.", section.name.c_str());
|
||||
std::span<const u8> data = std::span(elf.image).subspan(section.header.offset, section.header.size);
|
||||
|
||||
CCC_CHECK(section.header.link != 0, "Section '%s' has no linked string table.", section.name.c_str());
|
||||
CCC_CHECK(section.header.link < elf.sections.size(),
|
||||
"Section '%s' has out of range link field.", section.name.c_str());
|
||||
const ElfSection& linked_section = elf.sections[section.header.link];
|
||||
|
||||
CCC_CHECK(linked_section.header.offset + linked_section.header.size <= elf.image.size(),
|
||||
"Linked section '%s' out of range.", linked_section.name.c_str());
|
||||
std::span<const u8> linked_data = std::span(elf.image).subspan(
|
||||
linked_section.header.offset, linked_section.header.size);
|
||||
|
||||
symbol_table = std::make_unique<SymtabSymbolTable>(data, linked_data);
|
||||
|
||||
break;
|
||||
}
|
||||
case SNDLL: {
|
||||
CCC_CHECK(section.header.offset + section.header.size <= elf.image.size(),
|
||||
"Section '%s' out of range.", section.name.c_str());
|
||||
std::span<const u8> data = std::span(elf.image).subspan(section.header.offset, section.header.size);
|
||||
|
||||
if(data.size() >= 4 && data[0] != '\0') {
|
||||
Result<SNDLLFile> file = parse_sndll_file(data, Address::non_zero(section.header.addr), SNDLLType::SNDATA_SECTION);
|
||||
CCC_RETURN_IF_ERROR(file);
|
||||
|
||||
symbol_table = std::make_unique<SNDLLSymbolTable>(std::make_shared<SNDLLFile>(std::move(*file)));
|
||||
} else {
|
||||
CCC_WARN("Invalid SNDLL section.");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return symbol_table;
|
||||
}
|
||||
|
||||
Result<ModuleHandle> import_symbol_tables(
|
||||
SymbolDatabase& database,
|
||||
const std::vector<std::unique_ptr<SymbolTable>>& symbol_tables,
|
||||
std::string module_name,
|
||||
Address base_address,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler,
|
||||
const std::atomic_bool* interrupt)
|
||||
{
|
||||
Result<SymbolSourceHandle> module_source = database.get_symbol_source("Symbol Table Importer");
|
||||
CCC_RETURN_IF_ERROR(module_source);
|
||||
|
||||
Result<Module*> module_symbol = database.modules.create_symbol(
|
||||
std::move(module_name), base_address, *module_source, nullptr);
|
||||
CCC_RETURN_IF_ERROR(module_symbol);
|
||||
|
||||
ModuleHandle module_handle = (*module_symbol)->handle();
|
||||
|
||||
for(const std::unique_ptr<SymbolTable>& symbol_table : symbol_tables) {
|
||||
// Find a symbol source object with the right name, or create one if one
|
||||
// doesn't already exist.
|
||||
Result<SymbolSourceHandle> source = database.get_symbol_source(symbol_table->name());
|
||||
if(!source.success()) {
|
||||
database.destroy_symbols_from_module(module_handle, false);
|
||||
return source;
|
||||
}
|
||||
|
||||
// Import the symbol table.
|
||||
SymbolGroup group;
|
||||
group.source = *source;
|
||||
group.module_symbol = database.modules.symbol_from_handle(module_handle);
|
||||
|
||||
Result<void> result = symbol_table->import(
|
||||
database, group, importer_flags, demangler, interrupt);
|
||||
if(!result.success()) {
|
||||
database.destroy_symbols_from_module(module_handle, false);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return module_handle;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
MdebugSymbolTable::MdebugSymbolTable(std::span<const u8> image, s32 section_offset)
|
||||
: m_image(image), m_section_offset(section_offset) {}
|
||||
|
||||
const char* MdebugSymbolTable::name() const
|
||||
{
|
||||
return "MIPS Debug Symbol Table";
|
||||
}
|
||||
|
||||
Result<void> MdebugSymbolTable::import(
|
||||
SymbolDatabase& database,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler,
|
||||
const std::atomic_bool* interrupt) const
|
||||
{
|
||||
return mdebug::import_symbol_table(
|
||||
database, m_image, m_section_offset, group, importer_flags, demangler, interrupt);
|
||||
}
|
||||
|
||||
Result<void> MdebugSymbolTable::print_headers(FILE* out) const
|
||||
{
|
||||
mdebug::SymbolTableReader reader;
|
||||
|
||||
Result<void> reader_result = reader.init(m_image, m_section_offset);
|
||||
CCC_RETURN_IF_ERROR(reader_result);
|
||||
|
||||
reader.print_header(out);
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> MdebugSymbolTable::print_symbols(FILE* out, u32 flags) const
|
||||
{
|
||||
mdebug::SymbolTableReader reader;
|
||||
Result<void> reader_result = reader.init(m_image, m_section_offset);
|
||||
CCC_RETURN_IF_ERROR(reader_result);
|
||||
|
||||
Result<void> print_result = reader.print_symbols(
|
||||
out, flags & PRINT_LOCALS, flags & PRINT_PROCEDURE_DESCRIPTORS, flags & PRINT_EXTERNALS);
|
||||
CCC_RETURN_IF_ERROR(print_result);
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
SymtabSymbolTable::SymtabSymbolTable(std::span<const u8> symtab, std::span<const u8> strtab)
|
||||
: m_symtab(symtab), m_strtab(strtab) {}
|
||||
|
||||
const char* SymtabSymbolTable::name() const
|
||||
{
|
||||
return "ELF Symbol Table";
|
||||
}
|
||||
|
||||
Result<void> SymtabSymbolTable::import(
|
||||
SymbolDatabase& database,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler,
|
||||
const std::atomic_bool* interrupt) const
|
||||
{
|
||||
return elf::import_symbols(database, group, m_symtab, m_strtab, importer_flags, demangler);
|
||||
}
|
||||
|
||||
Result<void> SymtabSymbolTable::print_headers(FILE* out) const
|
||||
{
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> SymtabSymbolTable::print_symbols(FILE* out, u32 flags) const
|
||||
{
|
||||
Result<void> symbtab_result = elf::print_symbol_table(out, m_symtab, m_strtab);
|
||||
CCC_RETURN_IF_ERROR(symbtab_result);
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
SNDLLSymbolTable::SNDLLSymbolTable(std::shared_ptr<SNDLLFile> sndll)
|
||||
: m_sndll(std::move(sndll)) {}
|
||||
|
||||
const char* SNDLLSymbolTable::name() const
|
||||
{
|
||||
return "SNDLL Symbol Table";
|
||||
}
|
||||
|
||||
Result<void> SNDLLSymbolTable::import(
|
||||
SymbolDatabase& database,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler,
|
||||
const std::atomic_bool* interrupt) const
|
||||
{
|
||||
return import_sndll_symbols(database, *m_sndll, group, importer_flags, demangler);
|
||||
}
|
||||
|
||||
Result<void> SNDLLSymbolTable::print_headers(FILE* out) const
|
||||
{
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> SNDLLSymbolTable::print_symbols(FILE* out, u32 flags) const
|
||||
{
|
||||
print_sndll_symbols(out, *m_sndll);
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
ElfSectionHeadersSymbolTable::ElfSectionHeadersSymbolTable(const ElfFile& elf)
|
||||
: m_elf(elf) {}
|
||||
|
||||
const char* ElfSectionHeadersSymbolTable::name() const
|
||||
{
|
||||
return "ELF Section Headers";
|
||||
}
|
||||
|
||||
Result<void> ElfSectionHeadersSymbolTable::import(
|
||||
SymbolDatabase& database,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler,
|
||||
const std::atomic_bool* interrupt) const
|
||||
{
|
||||
return m_elf.create_section_symbols(database, group);
|
||||
}
|
||||
|
||||
Result<void> ElfSectionHeadersSymbolTable::print_headers(FILE* out) const
|
||||
{
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> ElfSectionHeadersSymbolTable::print_symbols(FILE* out, u32 flags) const
|
||||
{
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
}
|
||||
164
3rdparty/ccc/src/ccc/symbol_table.h
vendored
Normal file
164
3rdparty/ccc/src/ccc/symbol_table.h
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "symbol_database.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
// Determine which symbol tables are present in a given file.
|
||||
|
||||
enum SymbolTableFormat {
|
||||
MDEBUG = 0, // The infamous Third Eye symbol table
|
||||
SYMTAB = 1, // Standard ELF symbol table
|
||||
SNDLL = 2 // SNDLL section
|
||||
};
|
||||
|
||||
struct SymbolTableFormatInfo {
|
||||
SymbolTableFormat format;
|
||||
const char* format_name;
|
||||
const char* section_name;
|
||||
};
|
||||
|
||||
// All the supported symbol table formats, sorted from best to worst.
|
||||
extern const std::vector<SymbolTableFormatInfo> SYMBOL_TABLE_FORMATS;
|
||||
|
||||
const SymbolTableFormatInfo* symbol_table_format_from_enum(SymbolTableFormat format);
|
||||
const SymbolTableFormatInfo* symbol_table_format_from_name(const char* format_name);
|
||||
const SymbolTableFormatInfo* symbol_table_format_from_section(const char* section_name);
|
||||
|
||||
enum SymbolPrintFlags {
|
||||
PRINT_LOCALS = 1 << 0,
|
||||
PRINT_PROCEDURE_DESCRIPTORS = 1 << 1,
|
||||
PRINT_EXTERNALS = 1 << 2
|
||||
};
|
||||
|
||||
class SymbolTable {
|
||||
public:
|
||||
virtual ~SymbolTable() {}
|
||||
|
||||
virtual const char* name() const = 0;
|
||||
|
||||
// Imports this symbol table into the passed database.
|
||||
virtual Result<void> import(
|
||||
SymbolDatabase& database,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler,
|
||||
const std::atomic_bool* interrupt) const = 0;
|
||||
|
||||
// Print out all the field in the header structure if one exists.
|
||||
virtual Result<void> print_headers(FILE* out) const = 0;
|
||||
|
||||
// Print out all the symbols in the symbol table. For .mdebug symbol tables
|
||||
// the symbols are split between those that are local to a specific
|
||||
// translation unit and those that are external, which is what the
|
||||
// print_locals and print_externals parameters control.
|
||||
virtual Result<void> print_symbols(FILE* out, u32 flags) const = 0;
|
||||
};
|
||||
|
||||
struct ElfSection;
|
||||
struct ElfFile;
|
||||
|
||||
// Create a symbol table from an ELF section. The return value may be null.
|
||||
Result<std::unique_ptr<SymbolTable>> create_elf_symbol_table(
|
||||
const ElfSection& section, const ElfFile& elf, SymbolTableFormat format);
|
||||
|
||||
// Utility function to call import_symbol_table on all the passed symbol tables
|
||||
// and to generate a module handle.
|
||||
Result<ModuleHandle> import_symbol_tables(
|
||||
SymbolDatabase& database,
|
||||
const std::vector<std::unique_ptr<SymbolTable>>& symbol_tables,
|
||||
std::string module_name,
|
||||
Address base_address,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler,
|
||||
const std::atomic_bool* interrupt);
|
||||
|
||||
class MdebugSymbolTable : public SymbolTable {
|
||||
public:
|
||||
MdebugSymbolTable(std::span<const u8> image, s32 section_offset);
|
||||
|
||||
const char* name() const override;
|
||||
|
||||
Result<void> import(
|
||||
SymbolDatabase& database,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler,
|
||||
const std::atomic_bool* interrupt) const override;
|
||||
|
||||
Result<void> print_headers(FILE* out) const override;
|
||||
Result<void> print_symbols(FILE* out, u32 flags) const override;
|
||||
|
||||
protected:
|
||||
std::span<const u8> m_image;
|
||||
s32 m_section_offset;
|
||||
};
|
||||
|
||||
class SymtabSymbolTable : public SymbolTable {
|
||||
public:
|
||||
SymtabSymbolTable(std::span<const u8> symtab, std::span<const u8> strtab);
|
||||
|
||||
const char* name() const override;
|
||||
|
||||
Result<void> import(
|
||||
SymbolDatabase& database,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler,
|
||||
const std::atomic_bool* interrupt) const override;
|
||||
|
||||
Result<void> print_headers(FILE* out) const override;
|
||||
Result<void> print_symbols(FILE* out, u32 flags) const override;
|
||||
|
||||
protected:
|
||||
std::span<const u8> m_symtab;
|
||||
std::span<const u8> m_strtab;
|
||||
};
|
||||
|
||||
struct SNDLLFile;
|
||||
|
||||
class SNDLLSymbolTable : public SymbolTable {
|
||||
public:
|
||||
SNDLLSymbolTable(std::shared_ptr<SNDLLFile> sndll);
|
||||
|
||||
const char* name() const override;
|
||||
|
||||
Result<void> import(
|
||||
SymbolDatabase& database,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler,
|
||||
const std::atomic_bool* interrupt) const override;
|
||||
|
||||
Result<void> print_headers(FILE* out) const override;
|
||||
Result<void> print_symbols(FILE* out, u32 flags) const override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<SNDLLFile> m_sndll;
|
||||
};
|
||||
|
||||
class ElfSectionHeadersSymbolTable : public SymbolTable {
|
||||
public:
|
||||
ElfSectionHeadersSymbolTable(const ElfFile& elf);
|
||||
|
||||
const char* name() const override;
|
||||
|
||||
Result<void> import(
|
||||
SymbolDatabase& database,
|
||||
const SymbolGroup& group,
|
||||
u32 importer_flags,
|
||||
DemanglerFunctions demangler,
|
||||
const std::atomic_bool* interrupt) const override;
|
||||
|
||||
Result<void> print_headers(FILE* out) const override;
|
||||
Result<void> print_symbols(FILE* out, u32 flags) const override;
|
||||
protected:
|
||||
const ElfFile& m_elf;
|
||||
};
|
||||
|
||||
}
|
||||
176
3rdparty/ccc/src/ccc/util.cpp
vendored
Normal file
176
3rdparty/ccc/src/ccc/util.cpp
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "util.h"
|
||||
|
||||
namespace ccc {
|
||||
|
||||
static CustomErrorCallback custom_error_callback = nullptr;
|
||||
|
||||
Error format_error(const char* source_file, int source_line, const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
char message[4096];
|
||||
if(vsnprintf(message, sizeof(message), format, args) < 0) {
|
||||
strncpy(message, "Failed to generate error message.", sizeof(message));
|
||||
}
|
||||
|
||||
Error error;
|
||||
error.message = message;
|
||||
error.source_file = source_file;
|
||||
error.source_line = source_line;
|
||||
|
||||
va_end(args);
|
||||
return error;
|
||||
}
|
||||
|
||||
void report_error(const Error& error)
|
||||
{
|
||||
if(custom_error_callback) {
|
||||
custom_error_callback(error, ERROR_LEVEL_ERROR);
|
||||
} else {
|
||||
fprintf(stderr, "[%s:%d] " CCC_ANSI_COLOUR_RED "error:" CCC_ANSI_COLOUR_OFF " %s\n",
|
||||
error.source_file, error.source_line, error.message.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void report_warning(const Error& warning)
|
||||
{
|
||||
if(custom_error_callback) {
|
||||
custom_error_callback(warning, ERROR_LEVEL_WARNING);
|
||||
} else {
|
||||
fprintf(stderr, "[%s:%d] " CCC_ANSI_COLOUR_MAGENTA "warning:" CCC_ANSI_COLOUR_OFF " %s\n",
|
||||
warning.source_file, warning.source_line, warning.message.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void set_custom_error_callback(CustomErrorCallback callback)
|
||||
{
|
||||
custom_error_callback = callback;
|
||||
}
|
||||
|
||||
std::optional<std::string_view> get_string(std::span<const u8> bytes, u64 offset)
|
||||
{
|
||||
for(u64 i = offset; i < bytes.size(); i++) {
|
||||
if(bytes[i] == '\0') {
|
||||
return std::string_view(
|
||||
reinterpret_cast<const char*>(&bytes[offset]),
|
||||
reinterpret_cast<const char*>(&bytes[i]));
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::string merge_paths(const std::string& base, const std::string& path)
|
||||
{
|
||||
// Try to figure out if we're dealing with a Windows path of a UNIX path.
|
||||
bool is_windows_path = false;
|
||||
if(base.empty()) {
|
||||
is_windows_path = guess_is_windows_path(path.c_str());
|
||||
} else {
|
||||
is_windows_path = guess_is_windows_path(base.c_str());
|
||||
}
|
||||
|
||||
// Actually merge the paths. If path is the entire path, we don't need to
|
||||
// append base onto the front, so check for that now.
|
||||
bool is_absolute_unix = (path.size() >= 1) && (path[0] == '/' || path[0] == '\\');
|
||||
bool is_absolute_windows = (path.size() >= 3) && path[1] == ':' && (path[2] == '/' || path[2] == '\\');
|
||||
if(base.empty() || is_absolute_unix || is_absolute_windows) {
|
||||
return normalise_path(path.c_str(), is_windows_path);
|
||||
}
|
||||
return normalise_path((base + "/" + path).c_str(), is_windows_path);
|
||||
}
|
||||
|
||||
std::string normalise_path(const char* input, bool use_backslashes_as_path_separators)
|
||||
{
|
||||
bool is_absolute = false;
|
||||
std::optional<char> drive_letter;
|
||||
std::vector<std::string> parts;
|
||||
|
||||
// Parse the beginning of the path.
|
||||
if(*input == '/' || *input == '\\') { // UNIX path, drive relative Windows path or UNC Windows path.
|
||||
is_absolute = true;
|
||||
} else if(isalpha(*input) && input[1] == ':' && (input[2] == '/' || input[2] == '\\')) { // Absolute Windows path.
|
||||
is_absolute = true;
|
||||
drive_letter = toupper(*input);
|
||||
input += 2;
|
||||
} else {
|
||||
parts.emplace_back();
|
||||
}
|
||||
|
||||
// Parse the rest of the path.
|
||||
while(*input != 0) {
|
||||
if(*input == '/' || *input == '\\') {
|
||||
while(*input == '/' || *input == '\\') input++;
|
||||
parts.emplace_back();
|
||||
} else {
|
||||
parts.back() += *(input++);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove "." and ".." parts.
|
||||
for(s32 i = 0; i < (s32) parts.size(); i++) {
|
||||
if(parts[i] == ".") {
|
||||
parts.erase(parts.begin() + i);
|
||||
i--;
|
||||
} else if(parts[i] == ".." && i > 0 && parts[i - 1] != "..") {
|
||||
parts.erase(parts.begin() + i);
|
||||
parts.erase(parts.begin() + i - 1);
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Output the path in a normal form.
|
||||
std::string output;
|
||||
if(is_absolute) {
|
||||
if(drive_letter.has_value()) {
|
||||
output += *drive_letter;
|
||||
output += ":";
|
||||
}
|
||||
output += use_backslashes_as_path_separators ? '\\' : '/';
|
||||
}
|
||||
for(size_t i = 0; i < parts.size(); i++) {
|
||||
output += parts[i];
|
||||
if(i != parts.size() - 1) {
|
||||
output += use_backslashes_as_path_separators ? '\\' : '/';
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
bool guess_is_windows_path(const char* path)
|
||||
{
|
||||
for(const char* ptr = path; *ptr != 0; ptr++) {
|
||||
if(*ptr == '\\') {
|
||||
return true;
|
||||
} else if(*ptr == '/') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string extract_file_name(const std::string& path)
|
||||
{
|
||||
std::string::size_type forward_pos = path.find_last_of('/');
|
||||
std::string::size_type backward_pos = path.find_last_of('\\');
|
||||
std::string::size_type pos;
|
||||
if(forward_pos == std::string::npos) {
|
||||
pos = backward_pos;
|
||||
} else if(backward_pos == std::string::npos) {
|
||||
pos = forward_pos;
|
||||
} else {
|
||||
pos = std::max(forward_pos, backward_pos);
|
||||
}
|
||||
if(pos + 1 != path.size() && pos != std::string::npos) {
|
||||
return path.substr(pos + 1);
|
||||
} else {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
341
3rdparty/ccc/src/ccc/util.h
vendored
Normal file
341
3rdparty/ccc/src/ccc/util.h
vendored
Normal file
@@ -0,0 +1,341 @@
|
||||
// This file is part of the Chaos Compiler Collection.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <span>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <cstdarg>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
|
||||
namespace ccc {
|
||||
|
||||
using u8 = unsigned char;
|
||||
using u16 = uint16_t;
|
||||
using u32 = uint32_t;
|
||||
using u64 = uint64_t;
|
||||
|
||||
using s8 = signed char;
|
||||
using s16 = int16_t;
|
||||
using s32 = int32_t;
|
||||
using s64 = int64_t;
|
||||
|
||||
#ifdef _WIN32
|
||||
#define CCC_ANSI_COLOUR_OFF ""
|
||||
#define CCC_ANSI_COLOUR_RED ""
|
||||
#define CCC_ANSI_COLOUR_MAGENTA ""
|
||||
#define CCC_ANSI_COLOUR_GRAY ""
|
||||
#else
|
||||
#define CCC_ANSI_COLOUR_OFF "\033[0m"
|
||||
#define CCC_ANSI_COLOUR_RED "\033[31m"
|
||||
#define CCC_ANSI_COLOUR_MAGENTA "\033[35m"
|
||||
#define CCC_ANSI_COLOUR_GRAY "\033[90m"
|
||||
#endif
|
||||
|
||||
struct Error {
|
||||
std::string message;
|
||||
const char* source_file;
|
||||
s32 source_line;
|
||||
};
|
||||
|
||||
enum ErrorLevel {
|
||||
ERROR_LEVEL_ERROR,
|
||||
ERROR_LEVEL_WARNING
|
||||
};
|
||||
|
||||
typedef void (*CustomErrorCallback)(const Error& error, ErrorLevel level);
|
||||
|
||||
Error format_error(const char* source_file, int source_line, const char* format, ...);
|
||||
void report_error(const Error& error);
|
||||
void report_warning(const Error& warning);
|
||||
void set_custom_error_callback(CustomErrorCallback callback);
|
||||
|
||||
#define CCC_FATAL(...) \
|
||||
{ \
|
||||
ccc::Error error = ccc::format_error(__FILE__, __LINE__, __VA_ARGS__); \
|
||||
ccc::report_error(error); \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#define CCC_CHECK_FATAL(condition, ...) \
|
||||
if(!(condition)) { \
|
||||
ccc::Error error = ccc::format_error(__FILE__, __LINE__, __VA_ARGS__); \
|
||||
ccc::report_error(error); \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#define CCC_ABORT_IF_FALSE(condition, ...) \
|
||||
if(!(condition)) { \
|
||||
ccc::Error error = ccc::format_error(__FILE__, __LINE__, __VA_ARGS__); \
|
||||
ccc::report_error(error); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#define CCC_ASSERT(condition) \
|
||||
CCC_ABORT_IF_FALSE(condition, #condition)
|
||||
|
||||
// The main error handling construct in CCC. This class is used to bundle
|
||||
// together a return value and a pointer to error information, so that errors
|
||||
// can be propagated up the stack.
|
||||
template <typename Value>
|
||||
class [[nodiscard]] Result {
|
||||
template <typename OtherValue>
|
||||
friend class Result;
|
||||
protected:
|
||||
Value m_value;
|
||||
std::unique_ptr<Error> m_error;
|
||||
|
||||
Result() {}
|
||||
|
||||
public:
|
||||
Result(Value value) : m_value(std::move(value)), m_error(nullptr) {}
|
||||
|
||||
// Used to propagate errors up the call stack.
|
||||
template <typename OtherValue>
|
||||
Result(Result<OtherValue>&& rhs)
|
||||
{
|
||||
CCC_ASSERT(rhs.m_error != nullptr);
|
||||
m_error = std::move(rhs.m_error);
|
||||
}
|
||||
|
||||
static Result<Value> failure(Error error)
|
||||
{
|
||||
Result<Value> result;
|
||||
result.m_error = std::make_unique<Error>(std::move(error));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool success() const
|
||||
{
|
||||
return m_error == nullptr;
|
||||
}
|
||||
|
||||
const Error& error() const
|
||||
{
|
||||
CCC_ASSERT(m_error != nullptr);
|
||||
return *m_error;
|
||||
}
|
||||
|
||||
Value& operator*()
|
||||
{
|
||||
CCC_ASSERT(m_error == nullptr);
|
||||
return m_value;
|
||||
}
|
||||
|
||||
const Value& operator*() const
|
||||
{
|
||||
CCC_ASSERT(m_error == nullptr);
|
||||
return m_value;
|
||||
}
|
||||
|
||||
Value* operator->()
|
||||
{
|
||||
CCC_ASSERT(m_error == nullptr);
|
||||
return &m_value;
|
||||
}
|
||||
|
||||
const Value* operator->() const
|
||||
{
|
||||
CCC_ASSERT(m_error == nullptr);
|
||||
return &m_value;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class [[nodiscard]] Result<void> : public Result<int> {
|
||||
public:
|
||||
Result() : Result<int>(0) {}
|
||||
|
||||
// Used to propagate errors up the call stack.
|
||||
template <typename OtherValue>
|
||||
Result(Result<OtherValue>&& rhs)
|
||||
{
|
||||
CCC_ASSERT(rhs.m_error != nullptr);
|
||||
m_error = std::move(rhs.m_error);
|
||||
}
|
||||
};
|
||||
|
||||
#define CCC_FAILURE(...) ccc::Result<int>::failure(ccc::format_error(__FILE__, __LINE__, __VA_ARGS__))
|
||||
|
||||
#define CCC_CHECK(condition, ...) \
|
||||
if(!(condition)) { \
|
||||
return CCC_FAILURE(__VA_ARGS__); \
|
||||
}
|
||||
|
||||
#define CCC_EXPECT_CHAR(input, c, context) \
|
||||
CCC_CHECK(*(input++) == c, \
|
||||
"Expected '%c' in %s, got '%c' (%02hhx)", \
|
||||
c, context, *(input - 1), *(input - 1))
|
||||
|
||||
#define CCC_RETURN_IF_ERROR(result) \
|
||||
if(!(result).success()) { \
|
||||
return (result); \
|
||||
}
|
||||
|
||||
#define CCC_EXIT_IF_ERROR(result) \
|
||||
if(!(result).success()) { \
|
||||
ccc::report_error((result).error()); \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#define CCC_GTEST_FAIL_IF_ERROR(result) \
|
||||
if(!(result).success()) { \
|
||||
FAIL() << (result).error().message; \
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void warn_impl(const char* source_file, int source_line, const char* format, Args... args)
|
||||
{
|
||||
Error warning = format_error(source_file, source_line, format, args...);
|
||||
report_warning(warning);
|
||||
}
|
||||
#define CCC_WARN(...) \
|
||||
ccc::warn_impl(__FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define CCC_PACKED_STRUCT(name, ...) \
|
||||
__pragma(pack(push, 1)) struct name { __VA_ARGS__ } __pragma(pack(pop));
|
||||
#else
|
||||
#define CCC_PACKED_STRUCT(name, ...) \
|
||||
struct __attribute__((__packed__)) name { __VA_ARGS__ };
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
const T* get_aligned(std::span<const u8> bytes, u64 offset)
|
||||
{
|
||||
if(offset > bytes.size() || bytes.size() - offset < sizeof(T) || offset % alignof(T) != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return reinterpret_cast<const T*>(&bytes[offset]);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T* get_unaligned(std::span<const u8> bytes, u64 offset)
|
||||
{
|
||||
if(offset > bytes.size() || bytes.size() - offset < sizeof(T)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return reinterpret_cast<const T*>(&bytes[offset]);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::optional<T> copy_unaligned(std::span<const u8> bytes, u64 offset)
|
||||
{
|
||||
if(offset > bytes.size() || bytes.size() - offset < sizeof(T)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
T value;
|
||||
memcpy(&value, &bytes[offset], sizeof(T));
|
||||
return value;
|
||||
}
|
||||
|
||||
std::optional<std::string_view> get_string(std::span<const u8> bytes, u64 offset);
|
||||
|
||||
#define CCC_BEGIN_END(x) (x).begin(), (x).end()
|
||||
#define CCC_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#define CCC_FOURCC(string) ((string)[0] | (string)[1] << 8 | (string)[2] << 16 | (string)[3] << 24)
|
||||
|
||||
struct Address {
|
||||
u32 value = (u32) -1;
|
||||
|
||||
Address() {}
|
||||
Address(u32 v) : value(v) {}
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
return value != (u32) -1;
|
||||
}
|
||||
|
||||
u32 get_or_zero() const
|
||||
{
|
||||
if(valid()) {
|
||||
return value;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Address add_base_address(Address base_address) const
|
||||
{
|
||||
if(valid()) {
|
||||
return base_address.get_or_zero() + value;
|
||||
} else {
|
||||
return Address();
|
||||
}
|
||||
}
|
||||
|
||||
static Address non_zero(u32 address)
|
||||
{
|
||||
Address result;
|
||||
if(address != 0) {
|
||||
result = address;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
friend auto operator<=>(const Address& lhs, const Address& rhs) = default;
|
||||
};
|
||||
|
||||
struct AddressRange {
|
||||
Address low;
|
||||
Address high;
|
||||
|
||||
AddressRange() {}
|
||||
AddressRange(Address address) : low(address), high(address) {}
|
||||
AddressRange(Address l, Address h) : low(l), high(h) {}
|
||||
|
||||
friend auto operator<=>(const AddressRange& lhs, const AddressRange& rhs) = default;
|
||||
};
|
||||
|
||||
// These functions are to be used only for source file paths present in the
|
||||
// symbol table, since we want them to be handled consistently across different
|
||||
// platforms, which with std::filesystem::path doesn't seem to be possible.
|
||||
std::string merge_paths(const std::string& base, const std::string& path);
|
||||
std::string normalise_path(const char* input, bool use_backslashes_as_path_separators);
|
||||
bool guess_is_windows_path(const char* path);
|
||||
std::string extract_file_name(const std::string& path);
|
||||
|
||||
namespace ast { struct Node; }
|
||||
|
||||
// These are used to reference STABS types from other types within a single
|
||||
// translation unit. For most games these will just be a single number, the type
|
||||
// number. In some cases, for example with the homebrew SDK, type numbers are a
|
||||
// pair of two numbers surrounded by round brackets e.g. (1,23) where the first
|
||||
// number is the index of the include file to use (includes are listed for each
|
||||
// translation unit separately), and the second number is the type number.
|
||||
struct StabsTypeNumber {
|
||||
s32 file = -1;
|
||||
s32 type = -1;
|
||||
|
||||
friend auto operator<=>(const StabsTypeNumber& lhs, const StabsTypeNumber& rhs) = default;
|
||||
bool valid() const { return type > -1; }
|
||||
};
|
||||
|
||||
enum StorageClass {
|
||||
STORAGE_CLASS_NONE = 0,
|
||||
STORAGE_CLASS_TYPEDEF = 1,
|
||||
STORAGE_CLASS_EXTERN = 2,
|
||||
STORAGE_CLASS_STATIC = 3,
|
||||
STORAGE_CLASS_AUTO = 4,
|
||||
STORAGE_CLASS_REGISTER = 5
|
||||
};
|
||||
|
||||
// Function pointers for the GNU demangler functions, so we can build CCC as a
|
||||
// library without linking against the demangler.
|
||||
struct DemanglerFunctions {
|
||||
char* (*cplus_demangle)(const char *mangled, int options) = nullptr;
|
||||
char* (*cplus_demangle_opname)(const char *opname, int options) = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
15
3rdparty/cpuinfo/cpuinfo.vcxproj
vendored
15
3rdparty/cpuinfo/cpuinfo.vcxproj
vendored
@@ -30,13 +30,16 @@
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\duckstation\dep\cpuinfo\src\arm\cache.c">
|
||||
<ClCompile Include="src\arm\cache.c">
|
||||
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\duckstation\dep\cpuinfo\src\arm\uarch.c">
|
||||
<ClCompile Include="src\arm\uarch.c">
|
||||
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\duckstation\dep\cpuinfo\src\arm\windows\init.c">
|
||||
<ClCompile Include="src\arm\windows\init-by-logical-sys-info.c">
|
||||
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\arm\windows\init.c">
|
||||
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deps\clog\src\clog.c" />
|
||||
@@ -78,13 +81,13 @@
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\duckstation\dep\cpuinfo\src\arm\api.h">
|
||||
<ClInclude Include="src\arm\api.h">
|
||||
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\duckstation\dep\cpuinfo\src\arm\midr.h">
|
||||
<ClInclude Include="src\arm\midr.h">
|
||||
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\duckstation\dep\cpuinfo\src\arm\windows\api.h">
|
||||
<ClInclude Include="src\arm\windows\windows-arm-init.h">
|
||||
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deps\clog\include\clog.h" />
|
||||
|
||||
15
3rdparty/cpuinfo/cpuinfo.vcxproj.filters
vendored
15
3rdparty/cpuinfo/cpuinfo.vcxproj.filters
vendored
@@ -63,13 +63,16 @@
|
||||
<ClCompile Include="deps\clog\src\clog.c">
|
||||
<Filter>clog</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\duckstation\dep\cpuinfo\src\arm\cache.c">
|
||||
<ClCompile Include="src\arm\cache.c">
|
||||
<Filter>arm</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\duckstation\dep\cpuinfo\src\arm\uarch.c">
|
||||
<ClCompile Include="src\arm\uarch.c">
|
||||
<Filter>arm</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\duckstation\dep\cpuinfo\src\arm\windows\init.c">
|
||||
<ClCompile Include="src\arm\windows\init.c">
|
||||
<Filter>arm\windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\arm\windows\init-by-logical-sys-info.c">
|
||||
<Filter>arm\windows</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
@@ -99,13 +102,13 @@
|
||||
<ClInclude Include="deps\clog\include\clog.h">
|
||||
<Filter>clog</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\duckstation\dep\cpuinfo\src\arm\api.h">
|
||||
<ClInclude Include="src\arm\api.h">
|
||||
<Filter>arm</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\duckstation\dep\cpuinfo\src\arm\midr.h">
|
||||
<ClInclude Include="src\arm\midr.h">
|
||||
<Filter>arm</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\duckstation\dep\cpuinfo\src\arm\windows\api.h">
|
||||
<ClInclude Include="src\arm\windows\windows-arm-init.h">
|
||||
<Filter>arm\windows</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
|
||||
2
3rdparty/cpuinfo/include/cpuinfo-mock.h
vendored
2
3rdparty/cpuinfo/include/cpuinfo-mock.h
vendored
@@ -60,7 +60,7 @@ ssize_t CPUINFO_ABI cpuinfo_mock_read(int fd, void* buffer, size_t capacity);
|
||||
void CPUINFO_ABI cpuinfo_set_hwcap(uint32_t hwcap);
|
||||
#endif
|
||||
#if CPUINFO_ARCH_ARM
|
||||
void CPUINFO_ABI cpuinfo_set_hwcap2(uint32_t hwcap2);
|
||||
void CPUINFO_ABI cpuinfo_set_hwcap2(uint64_t hwcap2);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
101
3rdparty/cpuinfo/include/cpuinfo.h
vendored
101
3rdparty/cpuinfo/include/cpuinfo.h
vendored
@@ -419,6 +419,8 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_zen3 = 0x0020010B,
|
||||
/** AMD Zen 4 microarchitecture. */
|
||||
cpuinfo_uarch_zen4 = 0x0020010C,
|
||||
/** AMD Zen 5 microarchitecture. */
|
||||
cpuinfo_uarch_zen5 = 0x0020010D,
|
||||
|
||||
/** NSC Geode and AMD Geode GX and LX. */
|
||||
cpuinfo_uarch_geode = 0x00200200,
|
||||
@@ -496,13 +498,19 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_cortex_x2 = 0x00300502,
|
||||
/** ARM Cortex-X3. */
|
||||
cpuinfo_uarch_cortex_x3 = 0x00300503,
|
||||
/** ARM Cortex-X4. */
|
||||
cpuinfo_uarch_cortex_x4 = 0x00300504,
|
||||
|
||||
/** ARM Cortex-A510. */
|
||||
cpuinfo_uarch_cortex_a510 = 0x00300551,
|
||||
/** ARM Cortex-A520. */
|
||||
cpuinfo_uarch_cortex_a520 = 0x00300552,
|
||||
/** ARM Cortex-A710. */
|
||||
cpuinfo_uarch_cortex_a710 = 0x00300571,
|
||||
/** ARM Cortex-A715. */
|
||||
cpuinfo_uarch_cortex_a715 = 0x00300572,
|
||||
/** ARM Cortex-A720. */
|
||||
cpuinfo_uarch_cortex_a720 = 0x00300573,
|
||||
|
||||
/** Qualcomm Scorpion. */
|
||||
cpuinfo_uarch_scorpion = 0x00400100,
|
||||
@@ -514,6 +522,8 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_falkor = 0x00400103,
|
||||
/** Qualcomm Saphira. */
|
||||
cpuinfo_uarch_saphira = 0x00400104,
|
||||
/** Qualcomm Oryon. */
|
||||
cpuinfo_uarch_oryon = 0x00400105,
|
||||
|
||||
/** Nvidia Denver. */
|
||||
cpuinfo_uarch_denver = 0x00500100,
|
||||
@@ -812,6 +822,8 @@ struct cpuinfo_x86_isa {
|
||||
bool avx512vp2intersect;
|
||||
bool avx512_4vnniw;
|
||||
bool avx512_4fmaps;
|
||||
bool avx10_1;
|
||||
bool avx10_2;
|
||||
bool amx_bf16;
|
||||
bool amx_tile;
|
||||
bool amx_int8;
|
||||
@@ -1427,6 +1439,22 @@ static inline bool cpuinfo_has_x86_avx_ne_convert(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpuinfo_has_x86_avx10_1(void) {
|
||||
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
|
||||
return cpuinfo_isa.avx10_1;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpuinfo_has_x86_avx10_2(void) {
|
||||
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
|
||||
return cpuinfo_isa.avx10_2;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpuinfo_has_x86_hle(void) {
|
||||
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
|
||||
return cpuinfo_isa.hle;
|
||||
@@ -1664,6 +1692,14 @@ struct cpuinfo_arm_isa {
|
||||
bool sve;
|
||||
bool sve2;
|
||||
bool i8mm;
|
||||
bool sme;
|
||||
bool sme2;
|
||||
bool sme2p1;
|
||||
bool sme_i16i32;
|
||||
bool sme_bi32i32;
|
||||
bool sme_b16b16;
|
||||
bool sme_f16f16;
|
||||
uint32_t svelen;
|
||||
#endif
|
||||
bool rdm;
|
||||
bool fp16arith;
|
||||
@@ -2036,6 +2072,71 @@ static inline bool cpuinfo_has_arm_sve2(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Function to get the max SVE vector length on ARM CPU's which support SVE.
|
||||
static inline uint32_t cpuinfo_get_max_arm_sve_length(void) {
|
||||
#if CPUINFO_ARCH_ARM64
|
||||
return cpuinfo_isa.svelen * 8; // bytes * 8 = bit length(vector length)
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpuinfo_has_arm_sme(void) {
|
||||
#if CPUINFO_ARCH_ARM64
|
||||
return cpuinfo_isa.sme;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpuinfo_has_arm_sme2(void) {
|
||||
#if CPUINFO_ARCH_ARM64
|
||||
return cpuinfo_isa.sme2;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpuinfo_has_arm_sme2p1(void) {
|
||||
#if CPUINFO_ARCH_ARM64
|
||||
return cpuinfo_isa.sme2p1;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpuinfo_has_arm_sme_i16i32(void) {
|
||||
#if CPUINFO_ARCH_ARM64
|
||||
return cpuinfo_isa.sme_i16i32;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpuinfo_has_arm_sme_bi32i32(void) {
|
||||
#if CPUINFO_ARCH_ARM64
|
||||
return cpuinfo_isa.sme_bi32i32;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpuinfo_has_arm_sme_b16b16(void) {
|
||||
#if CPUINFO_ARCH_ARM64
|
||||
return cpuinfo_isa.sme_b16b16;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpuinfo_has_arm_sme_f16f16(void) {
|
||||
#if CPUINFO_ARCH_ARM64
|
||||
return cpuinfo_isa.sme_f16f16;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
|
||||
/* This structure is not a part of stable API. Use cpuinfo_has_riscv_* functions
|
||||
* instead. */
|
||||
|
||||
29
3rdparty/cpuinfo/src/arm/api.h
vendored
29
3rdparty/cpuinfo/src/arm/api.h
vendored
@@ -1,5 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define RESTRICT_STATIC /* nothing for MSVC */
|
||||
#else
|
||||
#define RESTRICT_STATIC restrict static
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -64,6 +70,7 @@ enum cpuinfo_arm_chipset_series {
|
||||
cpuinfo_arm_chipset_series_telechips_tcc,
|
||||
cpuinfo_arm_chipset_series_texas_instruments_omap,
|
||||
cpuinfo_arm_chipset_series_unisoc_t,
|
||||
cpuinfo_arm_chipset_series_unisoc_ums,
|
||||
cpuinfo_arm_chipset_series_wondermedia_wm,
|
||||
cpuinfo_arm_chipset_series_max,
|
||||
};
|
||||
@@ -81,11 +88,11 @@ struct cpuinfo_arm_chipset {
|
||||
|
||||
#ifndef __cplusplus
|
||||
CPUINFO_INTERNAL void cpuinfo_arm_chipset_to_string(
|
||||
const struct cpuinfo_arm_chipset chipset[restrict static 1],
|
||||
char name[restrict static CPUINFO_ARM_CHIPSET_NAME_MAX]);
|
||||
const struct cpuinfo_arm_chipset chipset[RESTRICT_STATIC 1],
|
||||
char name[RESTRICT_STATIC CPUINFO_ARM_CHIPSET_NAME_MAX]);
|
||||
|
||||
CPUINFO_INTERNAL void cpuinfo_arm_fixup_chipset(
|
||||
struct cpuinfo_arm_chipset chipset[restrict static 1],
|
||||
struct cpuinfo_arm_chipset chipset[RESTRICT_STATIC 1],
|
||||
uint32_t cores,
|
||||
uint32_t max_cpu_freq_max);
|
||||
|
||||
@@ -94,23 +101,23 @@ CPUINFO_INTERNAL void cpuinfo_arm_decode_vendor_uarch(
|
||||
#if CPUINFO_ARCH_ARM
|
||||
bool has_vfpv4,
|
||||
#endif
|
||||
enum cpuinfo_vendor vendor[restrict static 1],
|
||||
enum cpuinfo_uarch uarch[restrict static 1]);
|
||||
enum cpuinfo_vendor vendor[RESTRICT_STATIC 1],
|
||||
enum cpuinfo_uarch uarch[RESTRICT_STATIC 1]);
|
||||
|
||||
CPUINFO_INTERNAL void cpuinfo_arm_decode_cache(
|
||||
enum cpuinfo_uarch uarch,
|
||||
uint32_t cluster_cores,
|
||||
uint32_t midr,
|
||||
const struct cpuinfo_arm_chipset chipset[restrict static 1],
|
||||
const struct cpuinfo_arm_chipset chipset[RESTRICT_STATIC 1],
|
||||
uint32_t cluster_id,
|
||||
uint32_t arch_version,
|
||||
struct cpuinfo_cache l1i[restrict static 1],
|
||||
struct cpuinfo_cache l1d[restrict static 1],
|
||||
struct cpuinfo_cache l2[restrict static 1],
|
||||
struct cpuinfo_cache l3[restrict static 1]);
|
||||
struct cpuinfo_cache l1i[RESTRICT_STATIC 1],
|
||||
struct cpuinfo_cache l1d[RESTRICT_STATIC 1],
|
||||
struct cpuinfo_cache l2[RESTRICT_STATIC 1],
|
||||
struct cpuinfo_cache l3[RESTRICT_STATIC 1]);
|
||||
|
||||
CPUINFO_INTERNAL uint32_t
|
||||
cpuinfo_arm_compute_max_cache_size(const struct cpuinfo_processor processor[restrict static 1]);
|
||||
cpuinfo_arm_compute_max_cache_size(const struct cpuinfo_processor processor[RESTRICT_STATIC 1]);
|
||||
#else /* defined(__cplusplus) */
|
||||
CPUINFO_INTERNAL void cpuinfo_arm_decode_cache(
|
||||
enum cpuinfo_uarch uarch,
|
||||
|
||||
3
3rdparty/cpuinfo/src/arm/cache.c
vendored
3
3rdparty/cpuinfo/src/arm/cache.c
vendored
@@ -1341,7 +1341,8 @@ void cpuinfo_arm_decode_cache(
|
||||
* information, please refer to the technical manuals
|
||||
* linked above
|
||||
*/
|
||||
const uint32_t min_l2_size_KB = uarch == cpuinfo_uarch_neoverse_v2 ? 1024 : 256;
|
||||
const uint32_t min_l2_size_KB =
|
||||
(uarch == cpuinfo_uarch_neoverse_v2 || midr_is_ampere_altra(midr)) ? 1024 : 256;
|
||||
const uint32_t min_l3_size_KB = 0;
|
||||
|
||||
*l1i = (struct cpuinfo_cache){
|
||||
|
||||
4
3rdparty/cpuinfo/src/arm/linux/aarch32-isa.c
vendored
4
3rdparty/cpuinfo/src/arm/linux/aarch32-isa.c
vendored
@@ -24,7 +24,7 @@ void cpuinfo_set_wcid(uint32_t wcid) {
|
||||
|
||||
void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
|
||||
uint32_t features,
|
||||
uint32_t features2,
|
||||
uint64_t features2,
|
||||
uint32_t midr,
|
||||
uint32_t architecture_version,
|
||||
uint32_t architecture_flags,
|
||||
@@ -147,6 +147,8 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
|
||||
"VDOT instructions disabled: cause occasional SIGILL on Spreadtrum SC9863A");
|
||||
} else if (chipset->series == cpuinfo_arm_chipset_series_unisoc_t && chipset->model == 310) {
|
||||
cpuinfo_log_warning("VDOT instructions disabled: cause occasional SIGILL on Unisoc T310");
|
||||
} else if (chipset->series == cpuinfo_arm_chipset_series_unisoc_ums && chipset->model == 312) {
|
||||
cpuinfo_log_warning("VDOT instructions disabled: cause occasional SIGILL on Unisoc UMS312");
|
||||
} else {
|
||||
switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) {
|
||||
case UINT32_C(0x4100D0B0): /* Cortex-A76 */
|
||||
|
||||
42
3rdparty/cpuinfo/src/arm/linux/aarch64-isa.c
vendored
42
3rdparty/cpuinfo/src/arm/linux/aarch64-isa.c
vendored
@@ -3,9 +3,11 @@
|
||||
#include <arm/linux/api.h>
|
||||
#include <cpuinfo/log.h>
|
||||
|
||||
#include <sys/prctl.h>
|
||||
|
||||
void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
|
||||
uint32_t features,
|
||||
uint32_t features2,
|
||||
uint64_t features2,
|
||||
uint32_t midr,
|
||||
const struct cpuinfo_arm_chipset chipset[restrict static 1],
|
||||
struct cpuinfo_arm_isa isa[restrict static 1]) {
|
||||
@@ -142,6 +144,27 @@ void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
|
||||
if (features2 & CPUINFO_ARM_LINUX_FEATURE2_SVE2) {
|
||||
isa->sve2 = true;
|
||||
}
|
||||
if (features2 & CPUINFO_ARM_LINUX_FEATURE2_SME) {
|
||||
isa->sme = true;
|
||||
}
|
||||
if (features2 & CPUINFO_ARM_LINUX_FEATURE2_SME2) {
|
||||
isa->sme2 = true;
|
||||
}
|
||||
if (features2 & CPUINFO_ARM_LINUX_FEATURE2_SME2P1) {
|
||||
isa->sme2p1 = true;
|
||||
}
|
||||
if (features2 & CPUINFO_ARM_LINUX_FEATURE2_SME_I16I32) {
|
||||
isa->sme_i16i32 = true;
|
||||
}
|
||||
if (features2 & CPUINFO_ARM_LINUX_FEATURE2_SME_BI32I32) {
|
||||
isa->sme_bi32i32 = true;
|
||||
}
|
||||
if (features2 & CPUINFO_ARM_LINUX_FEATURE2_SME_B16B16) {
|
||||
isa->sme_b16b16 = true;
|
||||
}
|
||||
if (features2 & CPUINFO_ARM_LINUX_FEATURE2_SME_F16F16) {
|
||||
isa->sme_f16f16 = true;
|
||||
}
|
||||
// SVEBF16 is set iff SVE and BF16 are both supported, but the SVEBF16
|
||||
// feature flag was added in Linux kernel before the BF16 feature flag,
|
||||
// so we check for either.
|
||||
@@ -151,4 +174,21 @@ void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
|
||||
if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDFHM) {
|
||||
isa->fhm = true;
|
||||
}
|
||||
|
||||
#ifndef PR_SVE_GET_VL
|
||||
#define PR_SVE_GET_VL 51
|
||||
#endif
|
||||
|
||||
#ifndef PR_SVE_VL_LEN_MASK
|
||||
#define PR_SVE_VL_LEN_MASK 0xffff
|
||||
#endif
|
||||
|
||||
int ret = prctl(PR_SVE_GET_VL);
|
||||
if (ret < 0) {
|
||||
cpuinfo_log_warning("No SVE support on this machine");
|
||||
isa->svelen = 0; // Assume no SVE support if the call fails
|
||||
} else {
|
||||
// Mask out the SVE vector length bits
|
||||
isa->svelen = ret & PR_SVE_VL_LEN_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
19
3rdparty/cpuinfo/src/arm/linux/api.h
vendored
19
3rdparty/cpuinfo/src/arm/linux/api.h
vendored
@@ -137,6 +137,13 @@ struct cpuinfo_arm_linux_proc_cpuinfo_cache {
|
||||
#define CPUINFO_ARM_LINUX_FEATURE2_DGH UINT32_C(0x00008000)
|
||||
#define CPUINFO_ARM_LINUX_FEATURE2_RNG UINT32_C(0x00010000)
|
||||
#define CPUINFO_ARM_LINUX_FEATURE2_BTI UINT32_C(0x00020000)
|
||||
#define CPUINFO_ARM_LINUX_FEATURE2_SME UINT32_C(0x00800000)
|
||||
#define CPUINFO_ARM_LINUX_FEATURE2_SME2 UINT64_C(0x0000002000000000)
|
||||
#define CPUINFO_ARM_LINUX_FEATURE2_SME2P1 UINT64_C(0x0000004000000000)
|
||||
#define CPUINFO_ARM_LINUX_FEATURE2_SME_I16I32 UINT64_C(0x0000008000000000)
|
||||
#define CPUINFO_ARM_LINUX_FEATURE2_SME_BI32I32 UINT64_C(0x0000010000000000)
|
||||
#define CPUINFO_ARM_LINUX_FEATURE2_SME_B16B16 UINT64_C(0x0000020000000000)
|
||||
#define CPUINFO_ARM_LINUX_FEATURE2_SME_F16F16 UINT64_C(0x0000040000000000)
|
||||
#endif
|
||||
|
||||
#define CPUINFO_ARM_LINUX_VALID_ARCHITECTURE UINT32_C(0x00010000)
|
||||
@@ -172,7 +179,7 @@ struct cpuinfo_arm_linux_processor {
|
||||
struct cpuinfo_arm_linux_proc_cpuinfo_cache proc_cpuinfo_cache;
|
||||
#endif
|
||||
uint32_t features;
|
||||
uint32_t features2;
|
||||
uint64_t features2;
|
||||
/**
|
||||
* Main ID Register value.
|
||||
*/
|
||||
@@ -295,14 +302,14 @@ CPUINFO_INTERNAL bool cpuinfo_arm_linux_parse_proc_cpuinfo(
|
||||
#if CPUINFO_ARCH_ARM
|
||||
CPUINFO_INTERNAL bool cpuinfo_arm_linux_hwcap_from_getauxval(
|
||||
uint32_t hwcap[restrict static 1],
|
||||
uint32_t hwcap2[restrict static 1]);
|
||||
uint64_t hwcap2[restrict static 1]);
|
||||
CPUINFO_INTERNAL bool cpuinfo_arm_linux_hwcap_from_procfs(
|
||||
uint32_t hwcap[restrict static 1],
|
||||
uint32_t hwcap2[restrict static 1]);
|
||||
uint64_t hwcap2[restrict static 1]);
|
||||
|
||||
CPUINFO_INTERNAL void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
|
||||
uint32_t features,
|
||||
uint32_t features2,
|
||||
uint64_t features2,
|
||||
uint32_t midr,
|
||||
uint32_t architecture_version,
|
||||
uint32_t architecture_flags,
|
||||
@@ -311,11 +318,11 @@ CPUINFO_INTERNAL void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
|
||||
#elif CPUINFO_ARCH_ARM64
|
||||
CPUINFO_INTERNAL void cpuinfo_arm_linux_hwcap_from_getauxval(
|
||||
uint32_t hwcap[restrict static 1],
|
||||
uint32_t hwcap2[restrict static 1]);
|
||||
uint64_t hwcap2[restrict static 1]);
|
||||
|
||||
CPUINFO_INTERNAL void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
|
||||
uint32_t features,
|
||||
uint32_t features2,
|
||||
uint64_t features2,
|
||||
uint32_t midr,
|
||||
const struct cpuinfo_arm_chipset chipset[restrict static 1],
|
||||
struct cpuinfo_arm_isa isa[restrict static 1]);
|
||||
|
||||
76
3rdparty/cpuinfo/src/arm/linux/chipset.c
vendored
76
3rdparty/cpuinfo/src/arm/linux/chipset.c
vendored
@@ -85,6 +85,7 @@ static enum cpuinfo_arm_chipset_vendor chipset_series_vendor[cpuinfo_arm_chipset
|
||||
[cpuinfo_arm_chipset_series_telechips_tcc] = cpuinfo_arm_chipset_vendor_telechips,
|
||||
[cpuinfo_arm_chipset_series_texas_instruments_omap] = cpuinfo_arm_chipset_vendor_texas_instruments,
|
||||
[cpuinfo_arm_chipset_series_unisoc_t] = cpuinfo_arm_chipset_vendor_unisoc,
|
||||
[cpuinfo_arm_chipset_series_unisoc_ums] = cpuinfo_arm_chipset_vendor_unisoc,
|
||||
[cpuinfo_arm_chipset_series_wondermedia_wm] = cpuinfo_arm_chipset_vendor_wondermedia,
|
||||
};
|
||||
|
||||
@@ -959,6 +960,70 @@ static bool match_t(const char* start, const char* end, struct cpuinfo_arm_chips
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to match, case-sentitively, /Unisoc UMS\d{3,4}/ signature for Unisoc UMS
|
||||
* chipset. If match successful, extracts model information into \p chipset
|
||||
* argument.
|
||||
*
|
||||
* @param start - start of the platform identifier (/proc/cpuinfo Hardware
|
||||
* string, ro.product.board, ro.board.platform, or ro.chipname) to match.
|
||||
* @param end - end of the platform identifier (/proc/cpuinfo Hardware string,
|
||||
* ro.product.board, ro.board.platform, or ro.chipname) to match.
|
||||
* @param[out] chipset - location where chipset information will be stored upon
|
||||
* a successful match.
|
||||
*
|
||||
* @returns true if signature matched, false otherwise.
|
||||
*/
|
||||
static bool match_ums(const char* start, const char* end, struct cpuinfo_arm_chipset chipset[restrict static 1]) {
|
||||
/* Expect 13-14 symbols: "Unisoc UMS" (10 symbols) + 3-4-digit model number
|
||||
*/
|
||||
const size_t length = end - start;
|
||||
switch (length) {
|
||||
case 13:
|
||||
case 14:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check that string starts with "Unisoc UMS". The first four characters
|
||||
* are loaded as 32-bit little endian word */
|
||||
const uint32_t expected_unis = load_u32le(start);
|
||||
if (expected_unis != UINT32_C(0x73696E55) /* "sinU" = reverse("Unis") */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The next four characters are loaded as 32-bit little endian word */
|
||||
const uint32_t expected_oc_u = load_u32le(start + 4);
|
||||
if (expected_oc_u != UINT32_C(0x5520636F) /* "U co" = reverse("oc U") */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The next four characters are loaded as 16-bit little endian word */
|
||||
const uint16_t expected_ms = load_u16le(start + 8);
|
||||
if (expected_ms != UINT16_C(0x534D) /* "SM" = reverse("MS") */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Validate and parse 3-4 digit model number */
|
||||
uint32_t model = 0;
|
||||
for (uint32_t i = 10; i < length; i++) {
|
||||
const uint32_t digit = (uint32_t)(uint8_t)start[i] - '0';
|
||||
if (digit >= 10) {
|
||||
/* Not really a digit */
|
||||
return false;
|
||||
}
|
||||
model = model * 10 + digit;
|
||||
}
|
||||
|
||||
*chipset = (struct cpuinfo_arm_chipset){
|
||||
.vendor = cpuinfo_arm_chipset_vendor_unisoc,
|
||||
.series = cpuinfo_arm_chipset_series_unisoc_ums,
|
||||
.model = model,
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to match /lc\d{4}[a-z]?$/ signature for Leadcore LC chipsets.
|
||||
* If match successful, extracts model information into \p chipset argument.
|
||||
@@ -2508,6 +2573,16 @@ struct cpuinfo_arm_chipset cpuinfo_arm_linux_decode_chipset_from_proc_cpuinfo_ha
|
||||
return chipset;
|
||||
}
|
||||
|
||||
/* Check Unisoc UMS signature */
|
||||
if (match_ums(hardware, hardware_end, &chipset)) {
|
||||
cpuinfo_log_debug(
|
||||
"matched Unisoc UMS signature in /proc/cpuinfo Hardware string \"%.*s\"",
|
||||
(int)hardware_length,
|
||||
hardware);
|
||||
|
||||
return chipset;
|
||||
}
|
||||
|
||||
#if CPUINFO_ARCH_ARM
|
||||
/* Check Marvell PXA signature */
|
||||
if (match_pxa(hardware, hardware_end, &chipset)) {
|
||||
@@ -3726,6 +3801,7 @@ static const char* chipset_series_string[cpuinfo_arm_chipset_series_max] = {
|
||||
[cpuinfo_arm_chipset_series_telechips_tcc] = "TCC",
|
||||
[cpuinfo_arm_chipset_series_texas_instruments_omap] = "OMAP",
|
||||
[cpuinfo_arm_chipset_series_unisoc_t] = "T",
|
||||
[cpuinfo_arm_chipset_series_unisoc_ums] = "UMS",
|
||||
[cpuinfo_arm_chipset_series_wondermedia_wm] = "WM",
|
||||
};
|
||||
|
||||
|
||||
16
3rdparty/cpuinfo/src/arm/linux/hwcap.c
vendored
16
3rdparty/cpuinfo/src/arm/linux/hwcap.c
vendored
@@ -31,8 +31,8 @@ void cpuinfo_set_hwcap(uint32_t hwcap) {
|
||||
mock_hwcap = hwcap;
|
||||
}
|
||||
|
||||
static uint32_t mock_hwcap2 = 0;
|
||||
void cpuinfo_set_hwcap2(uint32_t hwcap2) {
|
||||
static uint64_t mock_hwcap2 = 0;
|
||||
void cpuinfo_set_hwcap2(uint64_t hwcap2) {
|
||||
mock_hwcap2 = hwcap2;
|
||||
}
|
||||
#endif
|
||||
@@ -40,7 +40,7 @@ void cpuinfo_set_hwcap2(uint32_t hwcap2) {
|
||||
#if CPUINFO_ARCH_ARM
|
||||
typedef unsigned long (*getauxval_function_t)(unsigned long);
|
||||
|
||||
bool cpuinfo_arm_linux_hwcap_from_getauxval(uint32_t hwcap[restrict static 1], uint32_t hwcap2[restrict static 1]) {
|
||||
bool cpuinfo_arm_linux_hwcap_from_getauxval(uint32_t hwcap[restrict static 1], uint64_t hwcap2[restrict static 1]) {
|
||||
#if CPUINFO_MOCK
|
||||
*hwcap = mock_hwcap;
|
||||
*hwcap2 = mock_hwcap2;
|
||||
@@ -83,13 +83,13 @@ cleanup:
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
bool cpuinfo_arm_linux_hwcap_from_procfs(uint32_t hwcap[restrict static 1], uint32_t hwcap2[restrict static 1]) {
|
||||
bool cpuinfo_arm_linux_hwcap_from_procfs(uint32_t hwcap[restrict static 1], uint64_t hwcap2[restrict static 1]) {
|
||||
#if CPUINFO_MOCK
|
||||
*hwcap = mock_hwcap;
|
||||
*hwcap2 = mock_hwcap2;
|
||||
return true;
|
||||
#else
|
||||
uint32_t hwcaps[2] = {0, 0};
|
||||
uint64_t hwcaps[2] = {0, 0};
|
||||
bool result = false;
|
||||
int file = -1;
|
||||
|
||||
@@ -113,7 +113,7 @@ bool cpuinfo_arm_linux_hwcap_from_procfs(uint32_t hwcap[restrict static 1], uint
|
||||
hwcaps[0] = (uint32_t)elf_auxv.a_un.a_val;
|
||||
break;
|
||||
case AT_HWCAP2:
|
||||
hwcaps[1] = (uint32_t)elf_auxv.a_un.a_val;
|
||||
hwcaps[1] = (uint64_t)elf_auxv.a_un.a_val;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -141,13 +141,13 @@ cleanup:
|
||||
}
|
||||
#endif /* __ANDROID__ */
|
||||
#elif CPUINFO_ARCH_ARM64
|
||||
void cpuinfo_arm_linux_hwcap_from_getauxval(uint32_t hwcap[restrict static 1], uint32_t hwcap2[restrict static 1]) {
|
||||
void cpuinfo_arm_linux_hwcap_from_getauxval(uint32_t hwcap[restrict static 1], uint64_t hwcap2[restrict static 1]) {
|
||||
#if CPUINFO_MOCK
|
||||
*hwcap = mock_hwcap;
|
||||
*hwcap2 = mock_hwcap2;
|
||||
#else
|
||||
*hwcap = (uint32_t)getauxval(AT_HWCAP);
|
||||
*hwcap2 = (uint32_t)getauxval(AT_HWCAP2);
|
||||
*hwcap2 = (uint64_t)getauxval(AT_HWCAP2);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
42
3rdparty/cpuinfo/src/arm/linux/init.c
vendored
42
3rdparty/cpuinfo/src/arm/linux/init.c
vendored
@@ -247,7 +247,8 @@ void cpuinfo_arm_linux_init(void) {
|
||||
#endif
|
||||
|
||||
#if CPUINFO_ARCH_ARM
|
||||
uint32_t isa_features = 0, isa_features2 = 0;
|
||||
uint32_t isa_features = 0;
|
||||
uint64_t isa_features2 = 0;
|
||||
#ifdef __ANDROID__
|
||||
/*
|
||||
* On Android before API 20, libc.so does not provide getauxval
|
||||
@@ -299,7 +300,8 @@ void cpuinfo_arm_linux_init(void) {
|
||||
&chipset,
|
||||
&cpuinfo_isa);
|
||||
#elif CPUINFO_ARCH_ARM64
|
||||
uint32_t isa_features = 0, isa_features2 = 0;
|
||||
uint32_t isa_features = 0;
|
||||
uint64_t isa_features2 = 0;
|
||||
/* getauxval is always available on ARM64 Android */
|
||||
cpuinfo_arm_linux_hwcap_from_getauxval(&isa_features, &isa_features2);
|
||||
cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
|
||||
@@ -333,18 +335,52 @@ void cpuinfo_arm_linux_init(void) {
|
||||
}
|
||||
|
||||
/* Propagate topology group IDs among siblings */
|
||||
bool detected_core_siblings_list_node = false;
|
||||
bool detected_cluster_cpus_list_node = false;
|
||||
for (uint32_t i = 0; i < arm_linux_processors_count; i++) {
|
||||
if (!bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arm_linux_processors[i].flags & CPUINFO_LINUX_FLAG_PACKAGE_ID) {
|
||||
if (!bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_FLAG_PACKAGE_ID)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Use the cluster_cpus_list topology node if available. If not
|
||||
* found, cache the result to avoid repeatedly attempting to
|
||||
* read the non-existent paths.
|
||||
* */
|
||||
if (!detected_core_siblings_list_node && !detected_cluster_cpus_list_node) {
|
||||
if (cpuinfo_linux_detect_cluster_cpus(
|
||||
arm_linux_processors_count,
|
||||
i,
|
||||
(cpuinfo_siblings_callback)cluster_siblings_parser,
|
||||
arm_linux_processors)) {
|
||||
detected_cluster_cpus_list_node = true;
|
||||
continue;
|
||||
} else {
|
||||
detected_core_siblings_list_node = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* The cached result above will guarantee only one of the blocks
|
||||
* below will execute, with a bias towards cluster_cpus_list.
|
||||
**/
|
||||
if (detected_core_siblings_list_node) {
|
||||
cpuinfo_linux_detect_core_siblings(
|
||||
arm_linux_processors_count,
|
||||
i,
|
||||
(cpuinfo_siblings_callback)cluster_siblings_parser,
|
||||
arm_linux_processors);
|
||||
}
|
||||
|
||||
if (detected_cluster_cpus_list_node) {
|
||||
cpuinfo_linux_detect_cluster_cpus(
|
||||
arm_linux_processors_count,
|
||||
i,
|
||||
(cpuinfo_siblings_callback)cluster_siblings_parser,
|
||||
arm_linux_processors);
|
||||
}
|
||||
}
|
||||
|
||||
/* Propagate all cluster IDs */
|
||||
|
||||
40
3rdparty/cpuinfo/src/arm/mach/init.c
vendored
40
3rdparty/cpuinfo/src/arm/mach/init.c
vendored
@@ -101,17 +101,34 @@ static enum cpuinfo_uarch decode_uarch(uint32_t cpu_family, uint32_t core_index,
|
||||
return cpuinfo_uarch_unknown;
|
||||
}
|
||||
|
||||
static void decode_package_name(char* package_name) {
|
||||
static int read_package_name_from_brand_string(char* package_name) {
|
||||
size_t size;
|
||||
if (sysctlbyname("machdep.cpu.brand_string", NULL, &size, NULL, 0) != 0) {
|
||||
sysctlfail:
|
||||
cpuinfo_log_warning("sysctlbyname(\"machdep.cpu.brand_string\") failed: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
char* brand_string = alloca(size);
|
||||
if (sysctlbyname("machdep.cpu.brand_string", brand_string, &size, NULL, 0) != 0)
|
||||
goto sysctlfail;
|
||||
cpuinfo_log_debug("machdep.cpu.brand_string: %s", brand_string);
|
||||
|
||||
strlcpy(package_name, brand_string, CPUINFO_PACKAGE_NAME_MAX);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int decode_package_name_from_hw_machine(char* package_name) {
|
||||
size_t size;
|
||||
if (sysctlbyname("hw.machine", NULL, &size, NULL, 0) != 0) {
|
||||
cpuinfo_log_warning("sysctlbyname(\"hw.machine\") failed: %s", strerror(errno));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
char* machine_name = alloca(size);
|
||||
if (sysctlbyname("hw.machine", machine_name, &size, NULL, 0) != 0) {
|
||||
cpuinfo_log_warning("sysctlbyname(\"hw.machine\") failed: %s", strerror(errno));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
cpuinfo_log_debug("hw.machine: %s", machine_name);
|
||||
|
||||
@@ -119,7 +136,7 @@ static void decode_package_name(char* package_name) {
|
||||
uint32_t major = 0, minor = 0;
|
||||
if (sscanf(machine_name, "%9[^,0123456789]%" SCNu32 ",%" SCNu32, name, &major, &minor) != 3) {
|
||||
cpuinfo_log_warning("parsing \"hw.machine\" failed: %s", strerror(errno));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t chip_model = 0;
|
||||
@@ -224,7 +241,9 @@ static void decode_package_name(char* package_name) {
|
||||
}
|
||||
if (chip_model != 0) {
|
||||
snprintf(package_name, CPUINFO_PACKAGE_NAME_MAX, "Apple A%" PRIu32 "%c", chip_model, suffix);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cpuinfo_arm_mach_init(void) {
|
||||
@@ -275,7 +294,8 @@ void cpuinfo_arm_mach_init(void) {
|
||||
.core_start = i * cores_per_package,
|
||||
.core_count = cores_per_package,
|
||||
};
|
||||
decode_package_name(packages[i].name);
|
||||
if (!read_package_name_from_brand_string(packages[i].name))
|
||||
decode_package_name_from_hw_machine(packages[i].name);
|
||||
}
|
||||
|
||||
const uint32_t cpu_family = get_sys_info_by_name("hw.cpufamily");
|
||||
@@ -399,6 +419,16 @@ void cpuinfo_arm_mach_init(void) {
|
||||
cpuinfo_isa.i8mm = true;
|
||||
}
|
||||
|
||||
const uint32_t has_feat_sme = get_sys_info_by_name("hw.optional.arm.FEAT_SME");
|
||||
if (has_feat_sme != 0) {
|
||||
cpuinfo_isa.sme = true;
|
||||
}
|
||||
|
||||
const uint32_t has_feat_sme2 = get_sys_info_by_name("hw.optional.arm.FEAT_SME2");
|
||||
if (has_feat_sme2 != 0) {
|
||||
cpuinfo_isa.sme2 = true;
|
||||
}
|
||||
|
||||
uint32_t num_clusters = 1;
|
||||
for (uint32_t i = 0; i < mach_topology.cores; i++) {
|
||||
cores[i] = (struct cpuinfo_core){
|
||||
|
||||
6
3rdparty/cpuinfo/src/arm/midr.h
vendored
6
3rdparty/cpuinfo/src/arm/midr.h
vendored
@@ -34,6 +34,7 @@
|
||||
#define CPUINFO_ARM_MIDR_KRYO_SILVER_820 UINT32_C(0x510F2110)
|
||||
#define CPUINFO_ARM_MIDR_EXYNOS_M1_M2 UINT32_C(0x530F0010)
|
||||
#define CPUINFO_ARM_MIDR_DENVER2 UINT32_C(0x4E0F0030)
|
||||
#define CPUINFO_ARM_MIDR_AMPERE_ALTRA UINT32_C(0x413fd0c1)
|
||||
|
||||
inline static uint32_t midr_set_implementer(uint32_t midr, uint32_t implementer) {
|
||||
return (midr & ~CPUINFO_ARM_MIDR_IMPLEMENTER_MASK) |
|
||||
@@ -167,6 +168,11 @@ inline static bool midr_is_kryo_gold(uint32_t midr) {
|
||||
return (midr & uarch_mask) == (CPUINFO_ARM_MIDR_KRYO_GOLD & uarch_mask);
|
||||
}
|
||||
|
||||
inline static bool midr_is_ampere_altra(uint32_t midr) {
|
||||
const uint32_t uarch_mask = CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK;
|
||||
return (midr & uarch_mask) == (CPUINFO_ARM_MIDR_AMPERE_ALTRA & uarch_mask);
|
||||
}
|
||||
|
||||
inline static uint32_t midr_score_core(uint32_t midr) {
|
||||
const uint32_t core_mask = CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK;
|
||||
switch (midr & core_mask) {
|
||||
|
||||
7
3rdparty/cpuinfo/src/arm/uarch.c
vendored
7
3rdparty/cpuinfo/src/arm/uarch.c
vendored
@@ -9,8 +9,8 @@ void cpuinfo_arm_decode_vendor_uarch(
|
||||
#if CPUINFO_ARCH_ARM
|
||||
bool has_vfpv4,
|
||||
#endif /* CPUINFO_ARCH_ARM */
|
||||
enum cpuinfo_vendor vendor[restrict static 1],
|
||||
enum cpuinfo_uarch uarch[restrict static 1]) {
|
||||
enum cpuinfo_vendor vendor[RESTRICT_STATIC 1],
|
||||
enum cpuinfo_uarch uarch[RESTRICT_STATIC 1]) {
|
||||
switch (midr_get_implementer(midr)) {
|
||||
case 'A':
|
||||
*vendor = cpuinfo_vendor_arm;
|
||||
@@ -332,6 +332,9 @@ void cpuinfo_arm_decode_vendor_uarch(
|
||||
*uarch = cpuinfo_uarch_cortex_a55;
|
||||
break;
|
||||
#if CPUINFO_ARCH_ARM64
|
||||
case 0x001:
|
||||
*uarch = cpuinfo_uarch_oryon;
|
||||
break;
|
||||
case 0xC00:
|
||||
*uarch = cpuinfo_uarch_falkor;
|
||||
break;
|
||||
|
||||
@@ -750,11 +750,14 @@ void store_core_info_per_processor(
|
||||
if (cores) {
|
||||
processors[processor_global_index].core = cores + core_id;
|
||||
cores[core_id].core_id = core_id;
|
||||
get_core_uarch_for_efficiency(
|
||||
chip_info->chip_name,
|
||||
core_info->Processor.EfficiencyClass,
|
||||
&(cores[core_id].uarch),
|
||||
&(cores[core_id].frequency));
|
||||
|
||||
if (chip_info->uarchs == NULL) {
|
||||
cpuinfo_log_error("uarch is NULL for core %d", core_id);
|
||||
return;
|
||||
}
|
||||
|
||||
cores[core_id].uarch = chip_info->uarchs[0].uarch;
|
||||
cores[core_id].frequency = chip_info->uarchs[0].frequency;
|
||||
|
||||
/* We don't have cluster information, so we handle it as
|
||||
* fixed 1 to (cluster / cores).
|
||||
|
||||
187
3rdparty/cpuinfo/src/arm/windows/init.c
vendored
187
3rdparty/cpuinfo/src/arm/windows/init.c
vendored
@@ -7,6 +7,9 @@
|
||||
#include <cpuinfo/internal-api.h>
|
||||
#include <cpuinfo/log.h>
|
||||
|
||||
#include <arm/api.h>
|
||||
#include <arm/midr.h>
|
||||
|
||||
#include "windows-arm-init.h"
|
||||
|
||||
struct cpuinfo_arm_isa cpuinfo_isa;
|
||||
@@ -14,62 +17,7 @@ struct cpuinfo_arm_isa cpuinfo_isa;
|
||||
static void set_cpuinfo_isa_fields(void);
|
||||
static struct woa_chip_info* get_system_info_from_registry(void);
|
||||
|
||||
static struct woa_chip_info woa_chip_unknown = {
|
||||
L"Unknown",
|
||||
woa_chip_name_unknown,
|
||||
{{cpuinfo_vendor_unknown, cpuinfo_uarch_unknown, 0}}};
|
||||
|
||||
/* Please add new SoC/chip info here! */
|
||||
static struct woa_chip_info woa_chips[woa_chip_name_last] = {
|
||||
/* Microsoft SQ1 Kryo 495 4 + 4 cores (3 GHz + 1.80 GHz) */
|
||||
[woa_chip_name_microsoft_sq_1] =
|
||||
{L"Microsoft SQ1",
|
||||
woa_chip_name_microsoft_sq_1,
|
||||
{{
|
||||
cpuinfo_vendor_arm,
|
||||
cpuinfo_uarch_cortex_a55,
|
||||
1800000000,
|
||||
},
|
||||
{
|
||||
cpuinfo_vendor_arm,
|
||||
cpuinfo_uarch_cortex_a76,
|
||||
3000000000,
|
||||
}}},
|
||||
/* Microsoft SQ2 Kryo 495 4 + 4 cores (3.15 GHz + 2.42 GHz) */
|
||||
[woa_chip_name_microsoft_sq_2] =
|
||||
{L"Microsoft SQ2",
|
||||
woa_chip_name_microsoft_sq_2,
|
||||
{{
|
||||
cpuinfo_vendor_arm,
|
||||
cpuinfo_uarch_cortex_a55,
|
||||
2420000000,
|
||||
},
|
||||
{cpuinfo_vendor_arm, cpuinfo_uarch_cortex_a76, 3150000000}}},
|
||||
/* Snapdragon (TM) 8cx Gen 3 @ 3.0 GHz */
|
||||
[woa_chip_name_microsoft_sq_3] =
|
||||
{L"Snapdragon (TM) 8cx Gen 3",
|
||||
woa_chip_name_microsoft_sq_3,
|
||||
{{
|
||||
cpuinfo_vendor_arm,
|
||||
cpuinfo_uarch_cortex_a78,
|
||||
2420000000,
|
||||
},
|
||||
{cpuinfo_vendor_arm, cpuinfo_uarch_cortex_x1, 3000000000}}},
|
||||
/* Microsoft Windows Dev Kit 2023 */
|
||||
[woa_chip_name_microsoft_sq_3_devkit] =
|
||||
{L"Snapdragon Compute Platform",
|
||||
woa_chip_name_microsoft_sq_3_devkit,
|
||||
{{
|
||||
cpuinfo_vendor_arm,
|
||||
cpuinfo_uarch_cortex_a78,
|
||||
2420000000,
|
||||
},
|
||||
{cpuinfo_vendor_arm, cpuinfo_uarch_cortex_x1, 3000000000}}},
|
||||
/* Ampere Altra */
|
||||
[woa_chip_name_ampere_altra] = {
|
||||
L"Ampere(R) Altra(R) Processor",
|
||||
woa_chip_name_ampere_altra,
|
||||
{{cpuinfo_vendor_arm, cpuinfo_uarch_neoverse_n1, 3000000000}}}};
|
||||
static struct woa_chip_info woa_chip_unknown = {L"Unknown", {{cpuinfo_vendor_unknown, cpuinfo_uarch_unknown, 0}}};
|
||||
|
||||
BOOL CALLBACK cpuinfo_arm_windows_init(PINIT_ONCE init_once, PVOID parameter, PVOID* context) {
|
||||
struct woa_chip_info* chip_info = NULL;
|
||||
@@ -87,23 +35,6 @@ BOOL CALLBACK cpuinfo_arm_windows_init(PINIT_ONCE init_once, PVOID parameter, PV
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_core_uarch_for_efficiency(
|
||||
enum woa_chip_name chip,
|
||||
BYTE EfficiencyClass,
|
||||
enum cpuinfo_uarch* uarch,
|
||||
uint64_t* frequency) {
|
||||
/* For currently supported WoA chips, the Efficiency class selects
|
||||
* the pre-defined little and big core.
|
||||
* Any further supported SoC's logic should be implemented here.
|
||||
*/
|
||||
if (uarch && frequency && chip < woa_chip_name_last && EfficiencyClass < MAX_WOA_VALID_EFFICIENCY_CLASSES) {
|
||||
*uarch = woa_chips[chip].uarchs[EfficiencyClass].uarch;
|
||||
*frequency = woa_chips[chip].uarchs[EfficiencyClass].frequency;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Static helper functions */
|
||||
|
||||
static wchar_t* read_registry(LPCWSTR subkey, LPCWSTR value) {
|
||||
@@ -149,40 +80,112 @@ static wchar_t* read_registry(LPCWSTR subkey, LPCWSTR value) {
|
||||
return text_buffer;
|
||||
}
|
||||
|
||||
static uint64_t read_registry_qword(LPCWSTR subkey, LPCWSTR value) {
|
||||
DWORD key_type = 0;
|
||||
DWORD data_size = sizeof(uint64_t);
|
||||
const DWORD flags = RRF_RT_REG_QWORD; /* Only read QWORD (REG_QWORD) values */
|
||||
uint64_t qword_value = 0;
|
||||
LSTATUS result = RegGetValueW(HKEY_LOCAL_MACHINE, subkey, value, flags, &key_type, &qword_value, &data_size);
|
||||
if (result != ERROR_SUCCESS || data_size != sizeof(uint64_t)) {
|
||||
cpuinfo_log_error("Registry QWORD read error");
|
||||
return 0;
|
||||
}
|
||||
return qword_value;
|
||||
}
|
||||
|
||||
static uint64_t read_registry_dword(LPCWSTR subkey, LPCWSTR value) {
|
||||
DWORD key_type = 0;
|
||||
DWORD data_size = sizeof(DWORD);
|
||||
DWORD dword_value = 0;
|
||||
LSTATUS result =
|
||||
RegGetValueW(HKEY_LOCAL_MACHINE, subkey, value, RRF_RT_REG_DWORD, &key_type, &dword_value, &data_size);
|
||||
if (result != ERROR_SUCCESS || data_size != sizeof(DWORD)) {
|
||||
cpuinfo_log_error("Registry DWORD read error");
|
||||
return 0;
|
||||
}
|
||||
return (uint64_t)dword_value;
|
||||
}
|
||||
|
||||
static wchar_t* wcsndup(const wchar_t* src, size_t n) {
|
||||
size_t len = wcsnlen(src, n);
|
||||
wchar_t* dup = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (len + 1) * sizeof(wchar_t));
|
||||
if (dup) {
|
||||
wcsncpy_s(dup, len + 1, src, len);
|
||||
dup[len] = L'\0';
|
||||
}
|
||||
return dup;
|
||||
}
|
||||
|
||||
static struct core_info_by_chip_name get_core_info_from_midr(uint32_t midr, uint64_t frequency) {
|
||||
struct core_info_by_chip_name info;
|
||||
enum cpuinfo_vendor vendor;
|
||||
enum cpuinfo_uarch uarch;
|
||||
|
||||
#if CPUINFO_ARCH_ARM
|
||||
bool has_vfpv4 = false;
|
||||
cpuinfo_arm_decode_vendor_uarch(midr, has_vfpv4, &vendor, &uarch);
|
||||
#else
|
||||
cpuinfo_arm_decode_vendor_uarch(midr, &vendor, &uarch);
|
||||
#endif
|
||||
|
||||
info.vendor = vendor;
|
||||
info.uarch = uarch;
|
||||
info.frequency = frequency;
|
||||
return info;
|
||||
}
|
||||
|
||||
static struct woa_chip_info* get_system_info_from_registry(void) {
|
||||
wchar_t* text_buffer = NULL;
|
||||
LPCWSTR cpu0_subkey = L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
|
||||
LPCWSTR chip_name_value = L"ProcessorNameString";
|
||||
LPCWSTR chip_midr_value = L"CP 4000";
|
||||
LPCWSTR chip_mhz_value = L"~MHz";
|
||||
struct woa_chip_info* chip_info = NULL;
|
||||
|
||||
HANDLE heap = GetProcessHeap();
|
||||
|
||||
/* Read processor model name from registry and find in the hard-coded
|
||||
* list. */
|
||||
text_buffer = read_registry(cpu0_subkey, chip_name_value);
|
||||
if (text_buffer == NULL) {
|
||||
cpuinfo_log_error("Registry read error");
|
||||
cpuinfo_log_error("Registry read error for processor name");
|
||||
return NULL;
|
||||
}
|
||||
for (uint32_t i = 0; i < (uint32_t)woa_chip_name_last; i++) {
|
||||
size_t compare_length = wcsnlen(woa_chips[i].chip_name_string, CPUINFO_PACKAGE_NAME_MAX);
|
||||
int compare_result = wcsncmp(text_buffer, woa_chips[i].chip_name_string, compare_length);
|
||||
if (compare_result == 0) {
|
||||
chip_info = woa_chips + i;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* https://developer.arm.com/documentation/100442/0100/register-descriptions/aarch32-system-registers/midr--main-id-register
|
||||
* Regedit for MIDR :
|
||||
*HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0\CP 4000
|
||||
*/
|
||||
uint64_t midr_qword = (uint32_t)read_registry_qword(cpu0_subkey, chip_midr_value);
|
||||
if (midr_qword == 0) {
|
||||
cpuinfo_log_error("Registry read error for MIDR value");
|
||||
return NULL;
|
||||
}
|
||||
// MIDR is only 32 bits, so we need to cast it to uint32_t
|
||||
uint32_t midr_value = (uint32_t)midr_qword;
|
||||
|
||||
/* Read the frequency from the registry
|
||||
* The value is in MHz, so we need to convert it to Hz */
|
||||
uint64_t frequency_mhz = read_registry_dword(cpu0_subkey, chip_mhz_value);
|
||||
if (frequency_mhz == 0) {
|
||||
cpuinfo_log_error("Registry read error for frequency value");
|
||||
return NULL;
|
||||
}
|
||||
// Convert MHz to Hz
|
||||
uint64_t frequency_hz = frequency_mhz * 1000000;
|
||||
|
||||
// Allocate chip_info before using it.
|
||||
chip_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct woa_chip_info));
|
||||
if (chip_info == NULL) {
|
||||
/* No match was found, so print a warning and assign the unknown
|
||||
* case. */
|
||||
cpuinfo_log_error(
|
||||
"Unknown chip model name '%ls'.\nPlease add new Windows on Arm SoC/chip support to arm/windows/init.c!",
|
||||
text_buffer);
|
||||
} else {
|
||||
cpuinfo_log_debug("detected chip model name: %s", chip_info->chip_name_string);
|
||||
cpuinfo_log_error("Heap allocation error for chip_info");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HeapFree(heap, 0, text_buffer);
|
||||
// set chip_info fields
|
||||
chip_info->chip_name_string = wcsndup(text_buffer, CPUINFO_PACKAGE_NAME_MAX - 1);
|
||||
chip_info->uarchs[0] = get_core_info_from_midr(midr_value, frequency_hz);
|
||||
|
||||
cpuinfo_log_debug("detected chip model name: %ls", chip_info->chip_name_string);
|
||||
|
||||
return chip_info;
|
||||
}
|
||||
|
||||
@@ -216,4 +219,4 @@ static void set_cpuinfo_isa_fields(void) {
|
||||
cpuinfo_isa.pmull = crypto;
|
||||
|
||||
cpuinfo_isa.crc32 = IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) != 0;
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,6 @@
|
||||
/* Efficiency class = 0 means little core, while 1 means big core for now. */
|
||||
#define MAX_WOA_VALID_EFFICIENCY_CLASSES 2
|
||||
|
||||
/* List of known and supported Windows on Arm SoCs/chips. */
|
||||
enum woa_chip_name {
|
||||
woa_chip_name_microsoft_sq_1 = 0,
|
||||
woa_chip_name_microsoft_sq_2 = 1,
|
||||
woa_chip_name_microsoft_sq_3 = 2,
|
||||
woa_chip_name_microsoft_sq_3_devkit = 3,
|
||||
woa_chip_name_ampere_altra = 4,
|
||||
woa_chip_name_unknown = 5,
|
||||
woa_chip_name_last = woa_chip_name_unknown
|
||||
};
|
||||
|
||||
/* Topology information hard-coded by SoC/chip name */
|
||||
struct core_info_by_chip_name {
|
||||
enum cpuinfo_vendor vendor;
|
||||
@@ -26,14 +15,7 @@ struct core_info_by_chip_name {
|
||||
*/
|
||||
struct woa_chip_info {
|
||||
wchar_t* chip_name_string;
|
||||
enum woa_chip_name chip_name;
|
||||
struct core_info_by_chip_name uarchs[MAX_WOA_VALID_EFFICIENCY_CLASSES];
|
||||
};
|
||||
|
||||
bool get_core_uarch_for_efficiency(
|
||||
enum woa_chip_name chip,
|
||||
BYTE EfficiencyClass,
|
||||
enum cpuinfo_uarch* uarch,
|
||||
uint64_t* frequency);
|
||||
|
||||
bool cpu_info_init_by_logical_sys_info(const struct woa_chip_info* chip_info, enum cpuinfo_vendor vendor);
|
||||
|
||||
26
3rdparty/cpuinfo/src/freebsd/topology.c
vendored
26
3rdparty/cpuinfo/src/freebsd/topology.c
vendored
@@ -24,8 +24,10 @@ static char* sysctl_str(const char* name) {
|
||||
size_t value_size = 0;
|
||||
if (sysctlbyname(name, NULL, &value_size, NULL, 0) != 0) {
|
||||
cpuinfo_log_error("sysctlbyname(\"%s\") failed: %s", name, strerror(errno));
|
||||
return NULL;
|
||||
} else if (value_size <= 0) {
|
||||
cpuinfo_log_error("sysctlbyname(\"%s\") returned invalid value size %zu", name, value_size);
|
||||
return NULL;
|
||||
}
|
||||
value_size += 1;
|
||||
char* value = calloc(value_size, 1);
|
||||
@@ -52,29 +54,22 @@ struct cpuinfo_freebsd_topology cpuinfo_freebsd_detect_topology(void) {
|
||||
if (!topology_spec) {
|
||||
return topology;
|
||||
}
|
||||
const char* group_tag = "<group level=\"1\" cache-level=\"0\">";
|
||||
char* p = strstr(topology_spec, group_tag);
|
||||
while (p) {
|
||||
const char* cpu_tag = "cpu count=\"";
|
||||
char* q = strstr(p, cpu_tag);
|
||||
if (q) {
|
||||
p = q + strlen(cpu_tag);
|
||||
topology.packages += atoi(p);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (topology.packages == 0) {
|
||||
const char* group_tag = "<group level=\"1\"";
|
||||
const char* group_tags[] = {"<group level=\"2\" cache-level=\"0\">", "<group level=\"1\" "};
|
||||
for (size_t i = 0; i < sizeof(group_tags) / sizeof(group_tags[0]); i++) {
|
||||
const char* group_tag = group_tags[i];
|
||||
char* p = strstr(topology_spec, group_tag);
|
||||
while (p) {
|
||||
topology.packages += 1;
|
||||
p++;
|
||||
p = strstr(p, group_tag);
|
||||
}
|
||||
if (topology.packages > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (topology.packages == 0) {
|
||||
cpuinfo_log_error("failed to parse topology_spec:%s", topology_spec);
|
||||
cpuinfo_log_error("failed to parse topology_spec: %s", topology_spec);
|
||||
free(topology_spec);
|
||||
goto fail;
|
||||
}
|
||||
@@ -84,6 +79,7 @@ struct cpuinfo_freebsd_topology cpuinfo_freebsd_detect_topology(void) {
|
||||
goto fail;
|
||||
}
|
||||
if (topology.cores < topology.packages) {
|
||||
cpuinfo_log_error("invalid numbers of package and core: %d %d", topology.packages, topology.cores);
|
||||
goto fail;
|
||||
}
|
||||
topology.threads_per_core = sysctl_int("kern.smp.threads_per_core");
|
||||
|
||||
26
3rdparty/cpuinfo/src/x86/freebsd/init.c
vendored
26
3rdparty/cpuinfo/src/x86/freebsd/init.c
vendored
@@ -135,6 +135,10 @@ void cpuinfo_x86_freebsd_init(void) {
|
||||
if (x86_processor.cache.l1i.size != 0 || x86_processor.cache.l1d.size != 0) {
|
||||
/* Assume that threads on the same core share L1 */
|
||||
threads_per_l1 = freebsd_topology.threads / freebsd_topology.cores;
|
||||
if (threads_per_l1 == 0) {
|
||||
cpuinfo_log_error("failed to detect threads_per_l1");
|
||||
goto cleanup;
|
||||
}
|
||||
cpuinfo_log_warning(
|
||||
"freebsd kernel did not report number of "
|
||||
"threads sharing L1 cache; assume %" PRIu32,
|
||||
@@ -154,6 +158,10 @@ void cpuinfo_x86_freebsd_init(void) {
|
||||
* the same package share L2 */
|
||||
threads_per_l2 = freebsd_topology.threads / freebsd_topology.packages;
|
||||
}
|
||||
if (threads_per_l2 == 0) {
|
||||
cpuinfo_log_error("failed to detect threads_per_l1");
|
||||
goto cleanup;
|
||||
}
|
||||
cpuinfo_log_warning(
|
||||
"freebsd kernel did not report number of "
|
||||
"threads sharing L2 cache; assume %" PRIu32,
|
||||
@@ -170,6 +178,10 @@ void cpuinfo_x86_freebsd_init(void) {
|
||||
* may be L4 cache as well)
|
||||
*/
|
||||
threads_per_l3 = freebsd_topology.threads / freebsd_topology.packages;
|
||||
if (threads_per_l3 == 0) {
|
||||
cpuinfo_log_error("failed to detect threads_per_l3");
|
||||
goto cleanup;
|
||||
}
|
||||
cpuinfo_log_warning(
|
||||
"freebsd kernel did not report number of "
|
||||
"threads sharing L3 cache; assume %" PRIu32,
|
||||
@@ -187,6 +199,10 @@ void cpuinfo_x86_freebsd_init(void) {
|
||||
* shared L4 (like on IBM POWER8).
|
||||
*/
|
||||
threads_per_l4 = freebsd_topology.threads;
|
||||
if (threads_per_l4 == 0) {
|
||||
cpuinfo_log_error("failed to detect threads_per_l4");
|
||||
goto cleanup;
|
||||
}
|
||||
cpuinfo_log_warning(
|
||||
"freebsd kernel did not report number of "
|
||||
"threads sharing L4 cache; assume %" PRIu32,
|
||||
@@ -203,7 +219,7 @@ void cpuinfo_x86_freebsd_init(void) {
|
||||
"%" PRIu32 " L1I caches",
|
||||
l1_count * sizeof(struct cpuinfo_cache),
|
||||
l1_count);
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
for (uint32_t c = 0; c < l1_count; c++) {
|
||||
l1i[c] = (struct cpuinfo_cache){
|
||||
@@ -230,7 +246,7 @@ void cpuinfo_x86_freebsd_init(void) {
|
||||
"%" PRIu32 " L1D caches",
|
||||
l1_count * sizeof(struct cpuinfo_cache),
|
||||
l1_count);
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
for (uint32_t c = 0; c < l1_count; c++) {
|
||||
l1d[c] = (struct cpuinfo_cache){
|
||||
@@ -257,7 +273,7 @@ void cpuinfo_x86_freebsd_init(void) {
|
||||
"%" PRIu32 " L2 caches",
|
||||
l2_count * sizeof(struct cpuinfo_cache),
|
||||
l2_count);
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
for (uint32_t c = 0; c < l2_count; c++) {
|
||||
l2[c] = (struct cpuinfo_cache){
|
||||
@@ -284,7 +300,7 @@ void cpuinfo_x86_freebsd_init(void) {
|
||||
"%" PRIu32 " L3 caches",
|
||||
l3_count * sizeof(struct cpuinfo_cache),
|
||||
l3_count);
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
for (uint32_t c = 0; c < l3_count; c++) {
|
||||
l3[c] = (struct cpuinfo_cache){
|
||||
@@ -311,7 +327,7 @@ void cpuinfo_x86_freebsd_init(void) {
|
||||
"%" PRIu32 " L4 caches",
|
||||
l4_count * sizeof(struct cpuinfo_cache),
|
||||
l4_count);
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
for (uint32_t c = 0; c < l4_count; c++) {
|
||||
l4[c] = (struct cpuinfo_cache){
|
||||
|
||||
14
3rdparty/cpuinfo/src/x86/isa.c
vendored
14
3rdparty/cpuinfo/src/x86/isa.c
vendored
@@ -46,6 +46,8 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
|
||||
(max_base_index >= 7) ? cpuidex(7, 0) : (struct cpuid_regs){0, 0, 0, 0};
|
||||
const struct cpuid_regs structured_feature_info1 =
|
||||
(max_base_index >= 7) ? cpuidex(7, 1) : (struct cpuid_regs){0, 0, 0, 0};
|
||||
const struct cpuid_regs structured_feature_info2 =
|
||||
(max_base_index >= 7) ? cpuidex(0x24, 0) : (struct cpuid_regs){0, 0, 0, 0};
|
||||
|
||||
const uint32_t processor_capacity_info_index = UINT32_C(0x80000008);
|
||||
const struct cpuid_regs processor_capacity_info = (max_extended_index >= processor_capacity_info_index)
|
||||
@@ -429,6 +431,18 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
|
||||
*/
|
||||
isa.avx512f = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00010000));
|
||||
|
||||
/*
|
||||
* AVX 10.1 instructions: avx 10 isa supported.
|
||||
* - Intel: edx[bit 19] in structured feature info (ecx = 1).
|
||||
*/
|
||||
isa.avx10_1 = avx512_regs && !!(structured_feature_info1.edx & UINT32_C(0x00080000));
|
||||
|
||||
/*
|
||||
* AVX 10.2 instructions: avx 10 version information.
|
||||
* - Intel: ebx[bits 0-7] in structured features info (eax = 24 ecx = 0).
|
||||
*/
|
||||
isa.avx10_2 = ((structured_feature_info2.ebx & UINT32_C(0x000000FF)) >= 2) && isa.avx10_1;
|
||||
|
||||
/*
|
||||
* AVX512PF instructions:
|
||||
* - Intel: ebx[bit 26] in structured feature info (ecx = 0).
|
||||
|
||||
5
3rdparty/cpuinfo/src/x86/linux/cpuinfo.c
vendored
5
3rdparty/cpuinfo/src/x86/linux/cpuinfo.c
vendored
@@ -83,8 +83,9 @@ struct proc_cpuinfo_parser_state {
|
||||
static bool parse_line(
|
||||
const char* line_start,
|
||||
const char* line_end,
|
||||
struct proc_cpuinfo_parser_state state[restrict static 1],
|
||||
void* context,
|
||||
uint64_t line_number) {
|
||||
struct proc_cpuinfo_parser_state* restrict state = context;
|
||||
/* Empty line. Skip. */
|
||||
if (line_start == line_end) {
|
||||
return true;
|
||||
@@ -215,5 +216,5 @@ bool cpuinfo_x86_linux_parse_proc_cpuinfo(
|
||||
.processors = processors,
|
||||
};
|
||||
return cpuinfo_linux_parse_multiline_file(
|
||||
"/proc/cpuinfo", BUFFER_SIZE, (cpuinfo_line_callback)parse_line, &state);
|
||||
"/proc/cpuinfo", BUFFER_SIZE, parse_line, &state);
|
||||
}
|
||||
|
||||
2
3rdparty/cpuinfo/src/x86/uarch.c
vendored
2
3rdparty/cpuinfo/src/x86/uarch.c
vendored
@@ -387,6 +387,8 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
|
||||
return cpuinfo_uarch_zen4;
|
||||
}
|
||||
break;
|
||||
case 0x1a:
|
||||
return cpuinfo_uarch_zen5;
|
||||
}
|
||||
break;
|
||||
case cpuinfo_vendor_hygon:
|
||||
|
||||
2
3rdparty/d3d12memalloc/LICENSE.txt
vendored
2
3rdparty/d3d12memalloc/LICENSE.txt
vendored
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
22
3rdparty/d3d12memalloc/README.md
vendored
22
3rdparty/d3d12memalloc/README.md
vendored
@@ -2,7 +2,7 @@
|
||||
|
||||
Easy to integrate memory allocation library for Direct3D 12.
|
||||
|
||||
**Documentation:** Browse online: [D3D12 Memory Allocator](https://gpuopen-librariesandsdks.github.io/D3D12MemoryAllocator/html/) (generated from Doxygen-style comments in [src/D3D12MemAlloc.h](src/D3D12MemAlloc.h))
|
||||
**Documentation:** Browse online: [D3D12 Memory Allocator](https://gpuopen-librariesandsdks.github.io/D3D12MemoryAllocator/html/) (generated from Doxygen-style comments in [include/D3D12MemAlloc.h](include/D3D12MemAlloc.h))
|
||||
|
||||
**License:** MIT. See [LICENSE.txt](LICENSE.txt)
|
||||
|
||||
@@ -36,6 +36,7 @@ Additional features:
|
||||
- Customization and integration with custom engines: Predefine appropriate macros to provide your own implementation of external facilities used by the library, like assert, mutex, and atomic.
|
||||
- Support for resource aliasing (overlap).
|
||||
- Custom memory pools: Create a pool with desired parameters (e.g. fixed or limited maximum size, custom `D3D12_HEAP_PROPERTIES` and `D3D12_HEAP_FLAGS`) and allocate memory out of it.
|
||||
- Support for GPU Upload Heaps from preview Agility SDK (needs compilation with `D3D12MA_OPTIONS16_SUPPORTED` macro).
|
||||
- Linear allocator: Create a pool with linear algorithm and use it for much faster allocations and deallocations in free-at-once, stack, double stack, or ring buffer fashion.
|
||||
- Defragmentation: Let the library move data around to free some memory blocks and make your allocations better compacted.
|
||||
- Statistics: Obtain brief or detailed statistics about the amount of memory used, unused, number of allocated heaps, number of allocations etc. - globally and per memory heap type. Current memory usage and budget as reported by the system can also be queried.
|
||||
@@ -101,15 +102,18 @@ This software package uses third party software:
|
||||
|
||||
For more information see [NOTICES.txt](NOTICES.txt).
|
||||
|
||||
# Software using this library
|
||||
|
||||
- **[The Forge](https://github.com/ConfettiFX/The-Forge)** - cross-platform rendering framework. Apache License 2.0.
|
||||
- **[Wicked Engine<img src="https://github.com/turanszkij/WickedEngine/blob/master/Content/logo_small.png" width="28px" align="center"/>](https://github.com/turanszkij/WickedEngine)** - 3D engine with modern graphics
|
||||
|
||||
[Some other projects on GitHub](https://github.com/search?q=D3D12MemAlloc.h&type=Code) and some game development studios that use DX12 in their games.
|
||||
|
||||
# See also
|
||||
|
||||
- **[Vcpkg](https://github.com/Microsoft/vcpkg)** dependency manager from Microsoft offers a port of this library that is easy to install.
|
||||
- **[Vulkan Memory Allocator](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/)** - equivalent library for Vulkan. License: MIT.
|
||||
- **[d3d12ma.c](https://github.com/milliewalky/d3d12ma.c)** - C bindings for this library. Author: Mateusz Maciejewski (Matt Walky). License: MIT.
|
||||
- **[TerraFX.Interop.D3D12MemoryAllocator](https://github.com/terrafx/terrafx.interop.d3d12memoryallocator)** - interop bindings for this library for C#, as used by [TerraFX](https://github.com/terrafx/terrafx). License: MIT.
|
||||
- **[Vulkan Memory Allocator](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/)** - equivalent library for Vulkan. License: MIT.
|
||||
|
||||
# Software using this library
|
||||
|
||||
- **[Qt Project](https://github.com/qt)**
|
||||
- **[Ghost of Tsushima: Director's Cut PC](https://www.youtube.com/watch?v=cPKBDbCYctc&t=698s)** - Information avaliable in 11:38 of credits
|
||||
- **[The Forge](https://github.com/ConfettiFX/The-Forge)** - cross-platform rendering framework. Apache License 2.0.
|
||||
- **[Wicked Engine<img src="https://github.com/turanszkij/WickedEngine/blob/master/Content/logo_small.png" width="28px" align="center"/>](https://github.com/turanszkij/WickedEngine)** - 3D engine with modern graphics
|
||||
|
||||
[Some other projects on GitHub](https://github.com/search?q=D3D12MemAlloc.h&type=Code) and some game development studios that use DX12 in their games.
|
||||
|
||||
81
3rdparty/d3d12memalloc/include/D3D12MemAlloc.h
vendored
81
3rdparty/d3d12memalloc/include/D3D12MemAlloc.h
vendored
@@ -24,9 +24,9 @@
|
||||
|
||||
/** \mainpage D3D12 Memory Allocator
|
||||
|
||||
<b>Version 2.1.0-development</b> (2023-07-05)
|
||||
<b>Version 2.1.0-development</b> (2024-07-05)
|
||||
|
||||
Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. \n
|
||||
Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. \n
|
||||
License: MIT
|
||||
|
||||
Documentation of all members: D3D12MemAlloc.h
|
||||
@@ -160,9 +160,9 @@ class D3D12MA_API IUnknownImpl : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual ~IUnknownImpl() = default;
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef();
|
||||
virtual ULONG STDMETHODCALLTYPE Release();
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
protected:
|
||||
virtual void ReleaseThis() { delete this; }
|
||||
private:
|
||||
@@ -265,18 +265,18 @@ enum ALLOCATION_FLAGS
|
||||
*/
|
||||
ALLOCATION_FLAG_CAN_ALIAS = 0x10,
|
||||
|
||||
/** Allocation strategy that chooses smallest possible free range for the allocation
|
||||
/** %Allocation strategy that chooses smallest possible free range for the allocation
|
||||
to minimize memory usage and fragmentation, possibly at the expense of allocation time.
|
||||
*/
|
||||
ALLOCATION_FLAG_STRATEGY_MIN_MEMORY = 0x00010000,
|
||||
|
||||
/** Allocation strategy that chooses first suitable free range for the allocation -
|
||||
/** %Allocation strategy that chooses first suitable free range for the allocation -
|
||||
not necessarily in terms of the smallest offset but the one that is easiest and fastest to find
|
||||
to minimize allocation time, possibly at the expense of allocation quality.
|
||||
*/
|
||||
ALLOCATION_FLAG_STRATEGY_MIN_TIME = 0x00020000,
|
||||
|
||||
/** Allocation strategy that chooses always the lowest offset in available space.
|
||||
/** %Allocation strategy that chooses always the lowest offset in available space.
|
||||
This is not the most efficient strategy but achieves highly packed data.
|
||||
Used internally by defragmentation, not recomended in typical usage.
|
||||
*/
|
||||
@@ -402,8 +402,9 @@ struct TotalStatistics
|
||||
- 1 = `D3D12_HEAP_TYPE_UPLOAD`
|
||||
- 2 = `D3D12_HEAP_TYPE_READBACK`
|
||||
- 3 = `D3D12_HEAP_TYPE_CUSTOM`
|
||||
- 4 = `D3D12_HEAP_TYPE_GPU_UPLOAD`
|
||||
*/
|
||||
DetailedStatistics HeapType[4];
|
||||
DetailedStatistics HeapType[5];
|
||||
/** \brief One element for each memory segment group located at the following indices:
|
||||
|
||||
- 0 = `DXGI_MEMORY_SEGMENT_GROUP_LOCAL`
|
||||
@@ -413,9 +414,9 @@ struct TotalStatistics
|
||||
|
||||
- When `IsUMA() == FALSE` (discrete graphics card):
|
||||
- `DXGI_MEMORY_SEGMENT_GROUP_LOCAL` (index 0) represents GPU memory
|
||||
(resources allocated in `D3D12_HEAP_TYPE_DEFAULT` or `D3D12_MEMORY_POOL_L1`).
|
||||
(resources allocated in `D3D12_HEAP_TYPE_DEFAULT`, `D3D12_HEAP_TYPE_GPU_UPLOAD` or `D3D12_MEMORY_POOL_L1`).
|
||||
- `DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL` (index 1) represents system memory
|
||||
(resources allocated in `D3D12_HEAP_TYPE_UPLOAD`, `D3D12_HEAP_TYPE_READBACK`, or `D3D12_MEMORY_POOL_L0`).
|
||||
(resources allocated in `D3D12_HEAP_TYPE_UPLOAD`, `D3D12_HEAP_TYPE_READBACK`, or `D3D12_MEMORY_POOL_L0`).
|
||||
- When `IsUMA() == TRUE` (integrated graphics chip):
|
||||
- `DXGI_MEMORY_SEGMENT_GROUP_LOCAL` = (index 0) represents memory shared for all the resources.
|
||||
- `DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL` = (index 1) is unused and always 0.
|
||||
@@ -542,26 +543,6 @@ public:
|
||||
*/
|
||||
LPCWSTR GetName() const { return m_Name; }
|
||||
|
||||
/** \brief Returns `TRUE` if the memory of the allocation was filled with zeros when the allocation was created.
|
||||
|
||||
Returns `TRUE` only if the allocator is sure that the entire memory where the
|
||||
allocation was created was filled with zeros at the moment the allocation was made.
|
||||
|
||||
Returns `FALSE` if the memory could potentially contain garbage data.
|
||||
If it's a render-target or depth-stencil texture, it then needs proper
|
||||
initialization with `ClearRenderTargetView`, `ClearDepthStencilView`, `DiscardResource`,
|
||||
or a copy operation, as described on page
|
||||
"ID3D12Device::CreatePlacedResource method - Notes on the required resource initialization" in Microsoft documentation.
|
||||
Please note that rendering a fullscreen triangle or quad to the texture as
|
||||
a render target is not a proper way of initialization!
|
||||
|
||||
See also articles:
|
||||
|
||||
- "Coming to DirectX 12: More control over memory allocation" on DirectX Developer Blog
|
||||
- ["Initializing DX12 Textures After Allocation and Aliasing"](https://asawicki.info/news_1724_initializing_dx12_textures_after_allocation_and_aliasing).
|
||||
*/
|
||||
BOOL WasZeroInitialized() const { return m_PackedData.WasZeroInitialized(); }
|
||||
|
||||
protected:
|
||||
void ReleaseThis() override;
|
||||
|
||||
@@ -620,29 +601,26 @@ private:
|
||||
{
|
||||
public:
|
||||
PackedData() :
|
||||
m_Type(0), m_ResourceDimension(0), m_ResourceFlags(0), m_TextureLayout(0), m_WasZeroInitialized(0) { }
|
||||
m_Type(0), m_ResourceDimension(0), m_ResourceFlags(0), m_TextureLayout(0) { }
|
||||
|
||||
Type GetType() const { return (Type)m_Type; }
|
||||
D3D12_RESOURCE_DIMENSION GetResourceDimension() const { return (D3D12_RESOURCE_DIMENSION)m_ResourceDimension; }
|
||||
D3D12_RESOURCE_FLAGS GetResourceFlags() const { return (D3D12_RESOURCE_FLAGS)m_ResourceFlags; }
|
||||
D3D12_TEXTURE_LAYOUT GetTextureLayout() const { return (D3D12_TEXTURE_LAYOUT)m_TextureLayout; }
|
||||
BOOL WasZeroInitialized() const { return (BOOL)m_WasZeroInitialized; }
|
||||
|
||||
void SetType(Type type);
|
||||
void SetResourceDimension(D3D12_RESOURCE_DIMENSION resourceDimension);
|
||||
void SetResourceFlags(D3D12_RESOURCE_FLAGS resourceFlags);
|
||||
void SetTextureLayout(D3D12_TEXTURE_LAYOUT textureLayout);
|
||||
void SetWasZeroInitialized(BOOL wasZeroInitialized) { m_WasZeroInitialized = wasZeroInitialized ? 1 : 0; }
|
||||
|
||||
private:
|
||||
UINT m_Type : 2; // enum Type
|
||||
UINT m_ResourceDimension : 3; // enum D3D12_RESOURCE_DIMENSION
|
||||
UINT m_ResourceFlags : 24; // flags D3D12_RESOURCE_FLAGS
|
||||
UINT m_TextureLayout : 9; // enum D3D12_TEXTURE_LAYOUT
|
||||
UINT m_WasZeroInitialized : 1; // BOOL
|
||||
} m_PackedData;
|
||||
|
||||
Allocation(AllocatorPimpl* allocator, UINT64 size, UINT64 alignment, BOOL wasZeroInitialized);
|
||||
Allocation(AllocatorPimpl* allocator, UINT64 size, UINT64 alignment);
|
||||
// Nothing here, everything already done in Release.
|
||||
virtual ~Allocation() = default;
|
||||
|
||||
@@ -1065,6 +1043,16 @@ enum ALLOCATOR_FLAGS
|
||||
to create its heaps on smaller alignment not suitable for MSAA textures.
|
||||
*/
|
||||
ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED = 0x8,
|
||||
/** \brief Disable optimization that prefers creating small buffers as committed to avoid 64 KB alignment.
|
||||
|
||||
By default, the library prefers creating small buffers <= 32 KB as committed,
|
||||
because drivers tend to pack them better, while placed buffers require 64 KB alignment.
|
||||
This, however, may decrease performance, as creating committed resources involves allocation of implicit heaps,
|
||||
which may take longer than creating placed resources in existing heaps.
|
||||
Passing this flag will disable this committed preference globally for the allocator.
|
||||
It can also be disabled for a single allocation by using #ALLOCATION_FLAG_STRATEGY_MIN_TIME.
|
||||
*/
|
||||
ALLOCATOR_FLAG_DONT_PREFER_SMALL_BUFFERS_COMMITTED = 0x10,
|
||||
};
|
||||
|
||||
/// \brief Parameters of created Allocator object. To be used with CreateAllocator().
|
||||
@@ -1130,6 +1118,15 @@ public:
|
||||
- "ID3D12Device::GetCustomHeapProperties method (d3d12.h)"
|
||||
*/
|
||||
BOOL IsCacheCoherentUMA() const;
|
||||
/** \brief Returns true if GPU Upload Heaps are supported on the current system.
|
||||
|
||||
When true, you can use `D3D12_HEAP_TYPE_GPU_UPLOAD`.
|
||||
|
||||
This flag is fetched from `D3D12_FEATURE_D3D12_OPTIONS16::GPUUploadHeapSupported`.
|
||||
|
||||
`#define D3D12MA_OPTIONS16_SUPPORTED 1` is needed for the compilation of this library. Otherwise the flag is always false.
|
||||
*/
|
||||
BOOL IsGPUUploadHeapSupported() const;
|
||||
/** \brief Returns total amount of memory of specific segment group, in bytes.
|
||||
|
||||
\param memorySegmentGroup use `DXGI_MEMORY_SEGMENT_GROUP_LOCAL` or DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL`.
|
||||
@@ -1447,11 +1444,11 @@ enum VIRTUAL_ALLOCATION_FLAGS
|
||||
*/
|
||||
VIRTUAL_ALLOCATION_FLAG_UPPER_ADDRESS = ALLOCATION_FLAG_UPPER_ADDRESS,
|
||||
|
||||
/// Allocation strategy that tries to minimize memory usage.
|
||||
/// %Allocation strategy that tries to minimize memory usage.
|
||||
VIRTUAL_ALLOCATION_FLAG_STRATEGY_MIN_MEMORY = ALLOCATION_FLAG_STRATEGY_MIN_MEMORY,
|
||||
/// Allocation strategy that tries to minimize allocation time.
|
||||
/// %Allocation strategy that tries to minimize allocation time.
|
||||
VIRTUAL_ALLOCATION_FLAG_STRATEGY_MIN_TIME = ALLOCATION_FLAG_STRATEGY_MIN_TIME,
|
||||
/** \brief Allocation strategy that chooses always the lowest offset in available space.
|
||||
/** %Allocation strategy that chooses always the lowest offset in available space.
|
||||
This is not the most efficient strategy but achieves highly packed data.
|
||||
*/
|
||||
VIRTUAL_ALLOCATION_FLAG_STRATEGY_MIN_OFFSET = ALLOCATION_FLAG_STRATEGY_MIN_OFFSET,
|
||||
@@ -1640,6 +1637,9 @@ ID3D12Device* device = (...)
|
||||
D3D12MA::ALLOCATOR_DESC allocatorDesc = {};
|
||||
allocatorDesc.pDevice = device;
|
||||
allocatorDesc.pAdapter = adapter;
|
||||
// These flags are optional but recommended.
|
||||
allocatorDesc.Flags = D3D12MA::ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED |
|
||||
D3D12MA::ALLOCATOR_FLAG_DEFAULT_POOLS_NOT_ZEROED;
|
||||
|
||||
D3D12MA::Allocator* allocator;
|
||||
HRESULT hr = D3D12MA::CreateAllocator(&allocatorDesc, &allocator);
|
||||
@@ -1864,6 +1864,9 @@ to obtain object D3D12MA::Pool. Example:
|
||||
\code
|
||||
POOL_DESC poolDesc = {};
|
||||
poolDesc.HeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
// These flags are optional but recommended.
|
||||
poolDesc.Flags = D3D12MA::POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED;
|
||||
poolDesc.HeapFlags = D3D12_HEAP_FLAG_CREATE_NOT_ZEROED;
|
||||
|
||||
Pool* pool;
|
||||
HRESULT hr = allocator->CreatePool(&poolDesc, &pool);
|
||||
|
||||
863
3rdparty/d3d12memalloc/src/D3D12MemAlloc.cpp
vendored
863
3rdparty/d3d12memalloc/src/D3D12MemAlloc.cpp
vendored
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user