Compare commits
585 Commits
v0.11.1
...
xgopilot/c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a451eef09 | ||
|
|
be4a5ba288 | ||
|
|
1ec0d09e95 | ||
|
|
1ba9618188 | ||
|
|
d2a22252c2 | ||
|
|
58352e3ee4 | ||
|
|
325e9a93b5 | ||
|
|
00dd09c7f4 | ||
|
|
1ed418e77e | ||
|
|
2110db7263 | ||
|
|
27efaa2eda | ||
|
|
355ff1009d | ||
|
|
e03f4dacfb | ||
|
|
75fa863da2 | ||
|
|
18ef7200bc | ||
|
|
bf05779f2f | ||
|
|
2b92b527e1 | ||
|
|
ed3176a6cc | ||
|
|
e5ebc32583 | ||
|
|
3ce198f103 | ||
|
|
e05c91530e | ||
|
|
8aadfde64a | ||
|
|
441b4b15a8 | ||
|
|
cf6cc937ef | ||
|
|
391e09a407 | ||
|
|
d6f45c67fb | ||
|
|
62198a59ba | ||
|
|
00d5aad528 | ||
|
|
72602d606d | ||
|
|
a99f3d9409 | ||
|
|
1edd4b863e | ||
|
|
c7e3408782 | ||
|
|
f65072d997 | ||
|
|
cadafde540 | ||
|
|
7e1abf1486 | ||
|
|
cf55925ff5 | ||
|
|
dba7bd498f | ||
|
|
8ce0574b9e | ||
|
|
dd4cf69e25 | ||
|
|
1ee4da9851 | ||
|
|
9e1b321ce6 | ||
|
|
b52caefebd | ||
|
|
0c63138ccd | ||
|
|
f40da557af | ||
|
|
0e28ac7ce4 | ||
|
|
4a6331c668 | ||
|
|
036bb858e2 | ||
|
|
5e86d1aee2 | ||
|
|
c4223df087 | ||
|
|
4cff9bb0a7 | ||
|
|
ccaf59ec62 | ||
|
|
087696e31b | ||
|
|
5592a8fc26 | ||
|
|
dc587f684d | ||
|
|
5e6501642d | ||
|
|
5f3c1e2de3 | ||
|
|
215bba2472 | ||
|
|
bcadacdf21 | ||
|
|
c24506b7e9 | ||
|
|
1811ca1220 | ||
|
|
f34ccc1b0c | ||
|
|
7180f20366 | ||
|
|
bb8e81fb9b | ||
|
|
21e7d62c7d | ||
|
|
35e9ffe31e | ||
|
|
62d0ee39de | ||
|
|
79f404ac88 | ||
|
|
8959c83397 | ||
|
|
67a3cb2e7e | ||
|
|
1195ce9b03 | ||
|
|
7323187f90 | ||
|
|
bbcbddfcad | ||
|
|
8fa3819714 | ||
|
|
c562f05b51 | ||
|
|
cc5c1144a7 | ||
|
|
db28648d29 | ||
|
|
03e617d902 | ||
|
|
e84f859d6c | ||
|
|
4b2e1e777c | ||
|
|
18e036568d | ||
|
|
e4f77f00a6 | ||
|
|
8bfe133bee | ||
|
|
897f944760 | ||
|
|
a202b484a9 | ||
|
|
17dfdd38c2 | ||
|
|
30a3e73d4f | ||
|
|
6170c1dcb9 | ||
|
|
cc65ee18b5 | ||
|
|
50d1d2e19a | ||
|
|
c3b674d804 | ||
|
|
3605eeeef7 | ||
|
|
729e5772a0 | ||
|
|
a2742a9de4 | ||
|
|
68947bfc1f | ||
|
|
e05c8b9f46 | ||
|
|
dc59333657 | ||
|
|
c50395b2b9 | ||
|
|
a1d7417684 | ||
|
|
0bbdb6c204 | ||
|
|
0ed3a54244 | ||
|
|
d5ad4d997d | ||
|
|
3cc8fd1c91 | ||
|
|
d0962d8adc | ||
|
|
d7b9968d9a | ||
|
|
b72311cd6d | ||
|
|
073e79d03b | ||
|
|
dd50d4dff0 | ||
|
|
b6d43ae88a | ||
|
|
89e93f9e7a | ||
|
|
0b6a558667 | ||
|
|
937f8339c7 | ||
|
|
a17f1f0bb0 | ||
|
|
8ce6c3b9ab | ||
|
|
d4474be921 | ||
|
|
6aa63121ff | ||
|
|
b239494a9f | ||
|
|
f573ebe40b | ||
|
|
95bd495d7b | ||
|
|
b1d95bb73c | ||
|
|
5dbf1a7561 | ||
|
|
0dbc686960 | ||
|
|
4e7526d68e | ||
|
|
fd17a43ade | ||
|
|
89af430329 | ||
|
|
64df39b3c5 | ||
|
|
e63ebb8151 | ||
|
|
7907e69719 | ||
|
|
849b23079b | ||
|
|
3be12dce44 | ||
|
|
f66bbb7fc3 | ||
|
|
9f48753203 | ||
|
|
e05f890b94 | ||
|
|
d0cf57fa95 | ||
|
|
92beb562bf | ||
|
|
6ce28e4d4e | ||
|
|
0340ef2a75 | ||
|
|
68623f0b27 | ||
|
|
13b5f39125 | ||
|
|
2a022be510 | ||
|
|
848432ea68 | ||
|
|
a19011897c | ||
|
|
9cea3226db | ||
|
|
bb89ef5c5d | ||
|
|
b39f0aa4bf | ||
|
|
1556b29e0a | ||
|
|
d46a3f2f49 | ||
|
|
7de4137d46 | ||
|
|
16b3473f52 | ||
|
|
1f7883654a | ||
|
|
fb94329c87 | ||
|
|
2f3c322076 | ||
|
|
922d174402 | ||
|
|
d9a20e8000 | ||
|
|
d2a021ceae | ||
|
|
66bf801fd6 | ||
|
|
20ce823b68 | ||
|
|
3ecf9b35f3 | ||
|
|
dba719a8d7 | ||
|
|
806b16c2c8 | ||
|
|
9eeb14ae31 | ||
|
|
df07513a37 | ||
|
|
16c8402065 | ||
|
|
c0afe199c2 | ||
|
|
1c2aea10f0 | ||
|
|
4e590d42be | ||
|
|
228d7cee31 | ||
|
|
c6676917b3 | ||
|
|
88e0844ada | ||
|
|
a2c9c7f10a | ||
|
|
9a5b231c88 | ||
|
|
519faabfe1 | ||
|
|
1a3bca40bc | ||
|
|
549beeb101 | ||
|
|
7cad146013 | ||
|
|
054591c279 | ||
|
|
da9865104f | ||
|
|
1033452e8f | ||
|
|
82ed8468e7 | ||
|
|
5e5d5c2a83 | ||
|
|
df8f67db5a | ||
|
|
e9170e4cef | ||
|
|
f41badde20 | ||
|
|
ac753070fa | ||
|
|
e6768584d7 | ||
|
|
7ca8abc788 | ||
|
|
e444c4b6ac | ||
|
|
0d02a7273e | ||
|
|
0c418073b3 | ||
|
|
2d1120bf69 | ||
|
|
22c26c1aaa | ||
|
|
c97d541936 | ||
|
|
f6bb1d9922 | ||
|
|
7ae6686f6b | ||
|
|
5a602830a6 | ||
|
|
00dbc91745 | ||
|
|
1684512308 | ||
|
|
40b142f947 | ||
|
|
e5c86fe936 | ||
|
|
9d7664373e | ||
|
|
825f0bd83f | ||
|
|
bedb454427 | ||
|
|
a9f74b7e55 | ||
|
|
002a68009e | ||
|
|
23b5e77dcc | ||
|
|
b8b0ae00d0 | ||
|
|
b58cce09ab | ||
|
|
a1f9afc88f | ||
|
|
6ba182afc7 | ||
|
|
da319e2a7c | ||
|
|
5e32a15146 | ||
|
|
07d69295b9 | ||
|
|
740a260708 | ||
|
|
96cd52dccc | ||
|
|
8650952145 | ||
|
|
58e5f5e4a1 | ||
|
|
7c792e8ca6 | ||
|
|
d3ded9f861 | ||
|
|
7f05aa54c2 | ||
|
|
77a7d9e549 | ||
|
|
0ff2d5d931 | ||
|
|
62fc21e22b | ||
|
|
6588f36123 | ||
|
|
977806affc | ||
|
|
dd3c1f923d | ||
|
|
1bd9ceb444 | ||
|
|
5a4c83ef85 | ||
|
|
82bb6e84d0 | ||
|
|
b99c073cca | ||
|
|
4b383b179a | ||
|
|
a8bc617e18 | ||
|
|
656a2a43b5 | ||
|
|
7e01f69d7e | ||
|
|
f875347ad9 | ||
|
|
1d3ecb287a | ||
|
|
0cac1c8a9d | ||
|
|
cb2fa5dd2d | ||
|
|
5997a296c2 | ||
|
|
96c5ce90e4 | ||
|
|
8ecbfe9ade | ||
|
|
012a5d7d69 | ||
|
|
997ea2849b | ||
|
|
1b3889ebc9 | ||
|
|
53e22488c8 | ||
|
|
19ddee0241 | ||
|
|
61143a6ff0 | ||
|
|
3f2fe83718 | ||
|
|
4639ee13e7 | ||
|
|
5810b29372 | ||
|
|
f3ecce86ee | ||
|
|
2160710884 | ||
|
|
71353baf59 | ||
|
|
6144987f06 | ||
|
|
b68686e542 | ||
|
|
0935d10edf | ||
|
|
fdc7d53904 | ||
|
|
69fe6d6377 | ||
|
|
cf2d1ef9ca | ||
|
|
ab57a13eb1 | ||
|
|
5587fd2885 | ||
|
|
f361d195f0 | ||
|
|
11e1348a2c | ||
|
|
ca30338066 | ||
|
|
e4218f90d7 | ||
|
|
3bfedb2588 | ||
|
|
d87deebbef | ||
|
|
76e4f4ab92 | ||
|
|
ddc61adc63 | ||
|
|
96001ce9b1 | ||
|
|
4a02b1f23b | ||
|
|
e40bdc196b | ||
|
|
508b23a584 | ||
|
|
b7181592a9 | ||
|
|
59e1df5478 | ||
|
|
ecaf7c8ac6 | ||
|
|
cd69092a60 | ||
|
|
f3de14da4b | ||
|
|
49b9b92790 | ||
|
|
1f193c8533 | ||
|
|
3ce63965bf | ||
|
|
50d8dbee05 | ||
|
|
c8eb871252 | ||
|
|
ad8aa6ac1a | ||
|
|
d3d39876d3 | ||
|
|
44cb4f2649 | ||
|
|
d0f89e456c | ||
|
|
90a16e8c90 | ||
|
|
ea6266c79f | ||
|
|
077f114373 | ||
|
|
2508674227 | ||
|
|
c9c703dfe6 | ||
|
|
d9dc4d5943 | ||
|
|
04f613dd15 | ||
|
|
0faef117ca | ||
|
|
f6bc5ac538 | ||
|
|
26fb156d6b | ||
|
|
d548671b91 | ||
|
|
ef1f2bce49 | ||
|
|
b428a8af08 | ||
|
|
9dfc6d1d52 | ||
|
|
6beb50b367 | ||
|
|
9e0c50dafe | ||
|
|
f5d4f93ed7 | ||
|
|
ae36ef4a0e | ||
|
|
485dbe4021 | ||
|
|
2f8f85a404 | ||
|
|
87c50cf22a | ||
|
|
6e20a435af | ||
|
|
2eb7d542d2 | ||
|
|
c414add29f | ||
|
|
372a09d2ca | ||
|
|
06568da140 | ||
|
|
96c7afcf3a | ||
|
|
5cfd996659 | ||
|
|
21189f378e | ||
|
|
9a90eaed76 | ||
|
|
d8122d14aa | ||
|
|
7bf0146e2f | ||
|
|
93ca632f7a | ||
|
|
49e5963b0a | ||
|
|
7e8df050a1 | ||
|
|
50a2650e67 | ||
|
|
1137749980 | ||
|
|
6de3bdcdd9 | ||
|
|
7c4fb8d6f1 | ||
|
|
a11a71eb93 | ||
|
|
b8d0a26bdc | ||
|
|
a8432252e1 | ||
|
|
56733e1dbd | ||
|
|
246278ff80 | ||
|
|
1b8b500fd7 | ||
|
|
e8bae52f66 | ||
|
|
3431354cb2 | ||
|
|
b2b407c2c2 | ||
|
|
1d76f515e0 | ||
|
|
fd0b2ff72d | ||
|
|
cbac24cf97 | ||
|
|
ff40a80569 | ||
|
|
c0a0e889e7 | ||
|
|
c5b4452a1b | ||
|
|
afee2beebe | ||
|
|
630b63744a | ||
|
|
1399c40243 | ||
|
|
a148964878 | ||
|
|
b831952e2e | ||
|
|
21174e44bb | ||
|
|
b650a546cd | ||
|
|
e580ecc55c | ||
|
|
04bb3eb5a9 | ||
|
|
28962a1c6c | ||
|
|
2fca50b7e5 | ||
|
|
3617c82e8b | ||
|
|
bf0f81afd7 | ||
|
|
ef07188534 | ||
|
|
5fe7ee9b6a | ||
|
|
a069e1d438 | ||
|
|
827f8b0e88 | ||
|
|
b9fdc2a25c | ||
|
|
d2d999d369 | ||
|
|
7b36cca86b | ||
|
|
843dd03553 | ||
|
|
6460724feb | ||
|
|
8e87bb6e86 | ||
|
|
3ac2929789 | ||
|
|
2a88d5777a | ||
|
|
b2c6534c92 | ||
|
|
303b620062 | ||
|
|
6940a5846b | ||
|
|
aa165829c6 | ||
|
|
56f90dbcf9 | ||
|
|
1e09f54e56 | ||
|
|
39f0877ba0 | ||
|
|
54dfd3c701 | ||
|
|
f43e2c0dee | ||
|
|
b03b8146df | ||
|
|
1f94cfbe57 | ||
|
|
6648e43bba | ||
|
|
87f4f618aa | ||
|
|
dab8379392 | ||
|
|
2fde31d782 | ||
|
|
7c4c8b8726 | ||
|
|
deea8754ae | ||
|
|
69c1787e22 | ||
|
|
3ac881b191 | ||
|
|
aa49fe665f | ||
|
|
b773de0815 | ||
|
|
49a5d3a350 | ||
|
|
6f829d0d43 | ||
|
|
daf0d7e56e | ||
|
|
0136344282 | ||
|
|
f571dde538 | ||
|
|
5424b53b62 | ||
|
|
86519b471e | ||
|
|
36fa18b28c | ||
|
|
d8da4364fd | ||
|
|
2538be9318 | ||
|
|
a9193e36ff | ||
|
|
0a6588c348 | ||
|
|
0c11c93b3a | ||
|
|
b80a54eb0f | ||
|
|
5eb833a984 | ||
|
|
66fd3a552d | ||
|
|
7f4b0d6215 | ||
|
|
5e6dd7644b | ||
|
|
a430e325ed | ||
|
|
e77c3a040d | ||
|
|
734b3a075e | ||
|
|
6b5f299ccd | ||
|
|
281b3ecf64 | ||
|
|
d7f2f4efdd | ||
|
|
08077f03f1 | ||
|
|
3d41514abd | ||
|
|
f2c16beab6 | ||
|
|
8983b146f2 | ||
|
|
8b0c6eae02 | ||
|
|
013f2ef00d | ||
|
|
e972be8dab | ||
|
|
e60c3bd943 | ||
|
|
417a5692e3 | ||
|
|
f0728c4fe0 | ||
|
|
249f85a25e | ||
|
|
9c59ac297d | ||
|
|
6e8f3d1d19 | ||
|
|
3df783de13 | ||
|
|
b469fc990f | ||
|
|
6df688e62e | ||
|
|
4f6f1c4453 | ||
|
|
891e47ef60 | ||
|
|
84f0c0fd9f | ||
|
|
25d64f2812 | ||
|
|
915cdf2c23 | ||
|
|
b7b6e3bc93 | ||
|
|
3d53b12dea | ||
|
|
132e240e87 | ||
|
|
0b233ea155 | ||
|
|
e9c96390e6 | ||
|
|
50bd078620 | ||
|
|
65f1c2589c | ||
|
|
695329b9dd | ||
|
|
4726e824a0 | ||
|
|
e68355d94f | ||
|
|
f5c08a2681 | ||
|
|
b14520954c | ||
|
|
04ac5de29d | ||
|
|
2118849d27 | ||
|
|
5e928b5ae1 | ||
|
|
3576ed36e2 | ||
|
|
fc88c89f7c | ||
|
|
f48b37a218 | ||
|
|
48bd1d46af | ||
|
|
20a7d0f120 | ||
|
|
84729e21b8 | ||
|
|
26aaa65c1d | ||
|
|
c863daf873 | ||
|
|
93197e7621 | ||
|
|
9001cdb8f2 | ||
|
|
e7e9530eb8 | ||
|
|
bdff346a20 | ||
|
|
4f5c95045d | ||
|
|
efabdf27c8 | ||
|
|
f36098d704 | ||
|
|
a5fd7f2eba | ||
|
|
0cb29ab388 | ||
|
|
9c66cb9b00 | ||
|
|
c2a50fa98d | ||
|
|
ac352179da | ||
|
|
f2f93c7f5f | ||
|
|
ce984d44a0 | ||
|
|
900ae67369 | ||
|
|
ffaac95c11 | ||
|
|
6fbc5c6fd0 | ||
|
|
f3c6d7e90f | ||
|
|
47c119a2d7 | ||
|
|
29904f8f22 | ||
|
|
fc86634e29 | ||
|
|
c89c845b98 | ||
|
|
452d840512 | ||
|
|
701568e011 | ||
|
|
dade77d719 | ||
|
|
ae8b7bb1f5 | ||
|
|
87c7b65223 | ||
|
|
71815a4963 | ||
|
|
69b2bfdeb2 | ||
|
|
57d74dfdbf | ||
|
|
450a3637e4 | ||
|
|
780c927ea6 | ||
|
|
254db35ef1 | ||
|
|
0463230533 | ||
|
|
44e1435c65 | ||
|
|
73270f0e87 | ||
|
|
c1550cf608 | ||
|
|
cd2e8aa40a | ||
|
|
bb70b6eeab | ||
|
|
9b28d2ac70 | ||
|
|
fd1def7885 | ||
|
|
9a79078441 | ||
|
|
bb43622fe7 | ||
|
|
9203c366e7 | ||
|
|
11a8af1db2 | ||
|
|
c8fb7eafa0 | ||
|
|
ffc1f712a3 | ||
|
|
cfc8687851 | ||
|
|
953699b2fd | ||
|
|
9a16fff27e | ||
|
|
ac0d104231 | ||
|
|
881efea006 | ||
|
|
f6a380d293 | ||
|
|
a971b93994 | ||
|
|
c4f0dd124d | ||
|
|
93b9b7d44c | ||
|
|
7552bfe39b | ||
|
|
2601faaff2 | ||
|
|
cb2e28d086 | ||
|
|
337877313a | ||
|
|
1693942cee | ||
|
|
867a1ce2f4 | ||
|
|
26b997537f | ||
|
|
19056b8a19 | ||
|
|
10d603b377 | ||
|
|
3f41c313ad | ||
|
|
d440949c1d | ||
|
|
64314dc6cf | ||
|
|
decb9d7f11 | ||
|
|
975b0b74ee | ||
|
|
9aa7807b02 | ||
|
|
337c6cfa25 | ||
|
|
f09a423ee7 | ||
|
|
3bf28f52c4 | ||
|
|
f794592f42 | ||
|
|
98bd05b47b | ||
|
|
3edbde0839 | ||
|
|
a2d92eac0b | ||
|
|
eb47c545ec | ||
|
|
c858f79449 | ||
|
|
27f6efbdec | ||
|
|
bba7494ffd | ||
|
|
0f79cad5a7 | ||
|
|
9e7bacbe23 | ||
|
|
2301a4834d | ||
|
|
40e0f58079 | ||
|
|
c23fb144cf | ||
|
|
caac681ac3 | ||
|
|
9ba3b3ef8f | ||
|
|
d7e523948b | ||
|
|
10a75138d1 | ||
|
|
d48b19c866 | ||
|
|
1fdcb55eba | ||
|
|
16cec9f045 | ||
|
|
438b0bd1b0 | ||
|
|
e8a91696d6 | ||
|
|
8882c31eb4 | ||
|
|
8455ee8226 | ||
|
|
3f74aded8a | ||
|
|
2e19c2013c | ||
|
|
1edaa2d09b | ||
|
|
beee018287 | ||
|
|
34266ea59d | ||
|
|
f26127ce98 | ||
|
|
ccf321d178 | ||
|
|
355721c47a | ||
|
|
d400663e5d | ||
|
|
2203be945a | ||
|
|
b9a2bf4b42 | ||
|
|
cc08195cf2 | ||
|
|
50c40a7828 | ||
|
|
158be3f949 | ||
|
|
0f87c322ca | ||
|
|
d5dd19b64c | ||
|
|
3ac9055493 | ||
|
|
3032d730b7 | ||
|
|
e93e7126b6 | ||
|
|
9bcf41d28f | ||
|
|
604ce47d5e | ||
|
|
e1ebe150d4 | ||
|
|
ae992737e8 | ||
|
|
c59d609eb8 | ||
|
|
9f26d12a3e | ||
|
|
9102577eba | ||
|
|
f0fcfde22b | ||
|
|
d9d813db56 | ||
|
|
a8808855ae | ||
|
|
5583f9418a | ||
|
|
7369ffd2aa | ||
|
|
ab15f30b13 | ||
|
|
8bff07d66b | ||
|
|
e2e2cb38be |
42
.github/actions/setup-deps/action.yml
vendored
42
.github/actions/setup-deps/action.yml
vendored
@@ -5,6 +5,10 @@ inputs:
|
||||
description: "LLVM version to install"
|
||||
required: true
|
||||
default: "19"
|
||||
install-llvm:
|
||||
description: "Whether to install LLVM"
|
||||
required: false
|
||||
default: "true"
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
@@ -14,9 +18,17 @@ runs:
|
||||
shell: bash
|
||||
run: |
|
||||
brew update
|
||||
brew install llvm@${{inputs.llvm-version}} lld@${{inputs.llvm-version}} bdw-gc openssl libffi libuv
|
||||
brew link --overwrite llvm@${{inputs.llvm-version}} lld@${{inputs.llvm-version}} libffi
|
||||
echo "$(brew --prefix llvm@${{inputs.llvm-version}})/bin" >> $GITHUB_PATH
|
||||
|
||||
# Install LLVM if requested
|
||||
if [[ "${{ inputs.install-llvm }}" == "true" ]]; then
|
||||
brew install llvm@${{inputs.llvm-version}} lld@${{inputs.llvm-version}}
|
||||
brew link --overwrite llvm@${{inputs.llvm-version}} lld@${{inputs.llvm-version}}
|
||||
echo "$(brew --prefix llvm@${{inputs.llvm-version}})/bin" >> $GITHUB_PATH
|
||||
fi
|
||||
|
||||
# Install common dependencies
|
||||
brew install bdw-gc openssl libffi libuv
|
||||
brew link --overwrite libffi
|
||||
|
||||
# Install optional deps for demos.
|
||||
#
|
||||
@@ -24,18 +36,29 @@ runs:
|
||||
opt_deps=(
|
||||
cjson # for github.com/goplus/lib/c/cjson
|
||||
sqlite # for github.com/goplus/lib/c/sqlite
|
||||
python@3.12 # for github.com/goplus/lib/py
|
||||
)
|
||||
brew install "${opt_deps[@]}"
|
||||
|
||||
brew install python@3.12 || true # for github.com/goplus/lib/py
|
||||
brew link --overwrite python@3.12
|
||||
|
||||
- name: Install Ubuntu dependencies
|
||||
if: runner.os == 'Linux'
|
||||
shell: bash
|
||||
run: |
|
||||
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-${{inputs.llvm-version}} main" | sudo tee /etc/apt/sources.list.d/llvm.list
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y llvm-${{inputs.llvm-version}}-dev clang-${{inputs.llvm-version}} libclang-${{inputs.llvm-version}}-dev lld-${{inputs.llvm-version}} pkg-config libgc-dev libssl-dev zlib1g-dev libffi-dev libcjson-dev libunwind-dev libuv1-dev
|
||||
echo "PATH=/usr/lib/llvm-${{inputs.llvm-version}}/bin:$PATH" >> $GITHUB_ENV
|
||||
# Install LLVM if requested
|
||||
if [[ "${{ inputs.install-llvm }}" == "true" ]]; then
|
||||
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-${{inputs.llvm-version}} main" | sudo tee /etc/apt/sources.list.d/llvm.list
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y llvm-${{inputs.llvm-version}}-dev clang-${{inputs.llvm-version}} libclang-${{inputs.llvm-version}}-dev lld-${{inputs.llvm-version}} libunwind-${{inputs.llvm-version}}-dev libc++-${{inputs.llvm-version}}-dev
|
||||
echo "PATH=/usr/lib/llvm-${{inputs.llvm-version}}/bin:$PATH" >> $GITHUB_ENV
|
||||
else
|
||||
sudo apt-get update
|
||||
fi
|
||||
|
||||
# Install common dependencies
|
||||
sudo apt-get install -y pkg-config libgc-dev libssl-dev zlib1g-dev libffi-dev libcjson-dev libuv1-dev
|
||||
|
||||
# Install optional deps for demos.
|
||||
#
|
||||
@@ -46,3 +69,4 @@ runs:
|
||||
python3.12-dev # for github.com/goplus/lib/py
|
||||
)
|
||||
sudo apt-get install -y "${opt_deps[@]}"
|
||||
|
||||
|
||||
28
.github/actions/setup-goreleaser/action.yml
vendored
Normal file
28
.github/actions/setup-goreleaser/action.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: "Setup GoReleaser"
|
||||
description: "Setup GoReleaser environment"
|
||||
inputs:
|
||||
linux-cache-key:
|
||||
description: "Linux sysroot cache key"
|
||||
required: true
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.24.x
|
||||
- name: Restore Linux sysroot cache
|
||||
id: cache-linux-sysroot
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: .sysroot/linux.tar.gz
|
||||
key: ${{ inputs.linux-cache-key }}
|
||||
- name: Populate Linux sysroot
|
||||
run: tar -xzvf .sysroot/linux.tar.gz -C .sysroot
|
||||
shell: bash
|
||||
- name: Check file
|
||||
run: tree .sysroot
|
||||
shell: bash
|
||||
- name: Get Esp clang
|
||||
run: bash .github/workflows/download_esp_clang.sh
|
||||
shell: bash
|
||||
38
.github/actions/test-helloworld/action.yml
vendored
38
.github/actions/test-helloworld/action.yml
vendored
@@ -1,11 +1,11 @@
|
||||
name: 'Test Hello World'
|
||||
description: 'Test Hello World with specific Go and module versions'
|
||||
name: "Test Hello World"
|
||||
description: "Test Hello World with specific Go and module versions"
|
||||
inputs:
|
||||
go-version:
|
||||
description: 'Go version being tested'
|
||||
description: "Go version being tested"
|
||||
required: true
|
||||
mod-version:
|
||||
description: 'Go module version to use'
|
||||
description: "Go module version to use"
|
||||
required: true
|
||||
runs:
|
||||
using: "composite"
|
||||
@@ -24,12 +24,40 @@ runs:
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/goplus/lib/c"
|
||||
"github.com/goplus/lib/cpp/std"
|
||||
)
|
||||
func main() {
|
||||
fmt.Println("Hello, LLGo!")
|
||||
println("Hello, LLGo!")
|
||||
c.Printf(c.Str("Hello, LLGo!\n"))
|
||||
c.Printf(std.Str("Hello LLGo by cpp/std.Str\n").CStr())
|
||||
}
|
||||
EOL
|
||||
go mod tidy
|
||||
llgo run .
|
||||
EXPECTED="Hello, LLGo!
|
||||
Hello, LLGo!
|
||||
Hello, LLGo!
|
||||
Hello LLGo by cpp/std.Str"
|
||||
OUTPUT=$(llgo run . 2>&1 | tee /dev/stderr)
|
||||
if echo "$OUTPUT" | grep -qF "$EXPECTED"; then
|
||||
echo "Basic test passed"
|
||||
else
|
||||
echo "Basic test failed"
|
||||
echo "Expected to contain:"
|
||||
echo "$EXPECTED"
|
||||
echo "Got:"
|
||||
echo "$OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd ../..
|
||||
mkdir -p _test/emb && cd _test/emb
|
||||
cat > main.go << 'EOL'
|
||||
package main
|
||||
|
||||
func main() {
|
||||
}
|
||||
EOL
|
||||
llgo build -v -target esp32-coreboard-v2 -o demo.out .
|
||||
test -f demo.out.elf && echo "ESP32 cross-compilation test passed: demo.out.elf generated"
|
||||
exit $?
|
||||
|
||||
8
.github/codecov.yml
vendored
8
.github/codecov.yml
vendored
@@ -1,9 +1,15 @@
|
||||
coverage:
|
||||
ignore:
|
||||
- "chore"
|
||||
- "cmd/internal"
|
||||
- "cmd"
|
||||
- "cl/cltest"
|
||||
- "internal/build"
|
||||
- "internal/llgen"
|
||||
- "internal/mockable"
|
||||
- "internal/packages"
|
||||
- "internal/typepatch"
|
||||
- "internal/github"
|
||||
- "internal/firmware"
|
||||
- "internal/flash"
|
||||
- "internal/monitor"
|
||||
- "xtool"
|
||||
|
||||
33
.github/workflows/doc.yml
vendored
33
.github/workflows/doc.yml
vendored
@@ -2,18 +2,26 @@ name: Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["**"]
|
||||
branches:
|
||||
- "**"
|
||||
- "!dependabot/**"
|
||||
- "!xgopilot/**"
|
||||
pull_request:
|
||||
branches: ["**"]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
doc_verify:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "20"
|
||||
|
||||
@@ -31,14 +39,15 @@ jobs:
|
||||
|
||||
remote_install:
|
||||
continue-on-error: true
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- macos-latest
|
||||
- ubuntu-24.04
|
||||
- ubuntu-latest
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Go
|
||||
uses: ./.github/actions/setup-go
|
||||
@@ -67,17 +76,18 @@ jobs:
|
||||
|
||||
local_install:
|
||||
continue-on-error: true
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- macos-latest
|
||||
- ubuntu-24.04
|
||||
- ubuntu-latest
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.23"
|
||||
|
||||
@@ -118,17 +128,18 @@ jobs:
|
||||
|
||||
local_install_full:
|
||||
continue-on-error: true
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- macos-latest
|
||||
- ubuntu-24.04
|
||||
- ubuntu-latest
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.23"
|
||||
|
||||
|
||||
67
.github/workflows/download_esp_clang.sh
vendored
Executable file
67
.github/workflows/download_esp_clang.sh
vendored
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
ESP_CLANG_VERSION="19.1.2_20250905-3"
|
||||
BASE_URL="https://github.com/goplus/espressif-llvm-project-prebuilt/releases/download/${ESP_CLANG_VERSION}"
|
||||
|
||||
get_esp_clang_platform() {
|
||||
local platform="$1"
|
||||
local os="${platform%-*}"
|
||||
local arch="${platform##*-}"
|
||||
|
||||
case "${os}" in
|
||||
"darwin")
|
||||
case "${arch}" in
|
||||
"amd64") echo "x86_64-apple-darwin" ;;
|
||||
"arm64") echo "aarch64-apple-darwin" ;;
|
||||
*) echo "Error: Unsupported darwin architecture: ${arch}" >&2; exit 1 ;;
|
||||
esac
|
||||
;;
|
||||
"linux")
|
||||
case "${arch}" in
|
||||
"amd64") echo "x86_64-linux-gnu" ;;
|
||||
"arm64") echo "aarch64-linux-gnu" ;;
|
||||
*) echo "Error: Unsupported linux architecture: ${arch}" >&2; exit 1 ;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Error: Unsupported OS: ${os}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
get_filename() {
|
||||
local platform="$1"
|
||||
local platform_suffix=$(get_esp_clang_platform "${platform}")
|
||||
echo "clang-esp-${ESP_CLANG_VERSION}-${platform_suffix}.tar.xz"
|
||||
}
|
||||
|
||||
download_and_extract() {
|
||||
local platform="$1"
|
||||
local os="${platform%-*}"
|
||||
local arch="${platform##*-}"
|
||||
local filename=$(get_filename "${platform}")
|
||||
local download_url="${BASE_URL}/${filename}"
|
||||
|
||||
echo "Downloading ESP Clang for ${platform}..."
|
||||
echo " URL: ${download_url}"
|
||||
|
||||
mkdir -p ".sysroot/${os}/${arch}/crosscompile/clang"
|
||||
curl -fsSL "${download_url}" | tar -xJ -C ".sysroot/${os}/${arch}/crosscompile/clang" --strip-components=1
|
||||
|
||||
if [[ ! -f ".sysroot/${os}/${arch}/crosscompile/clang/bin/clang++" ]]; then
|
||||
echo "Error: clang++ not found in ${platform} toolchain"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "${platform} ESP Clang ready in .sysroot/${os}/${arch}/crosscompile/clang"
|
||||
}
|
||||
|
||||
echo "Downloading ESP Clang toolchain version ${ESP_CLANG_VERSION}..."
|
||||
|
||||
for platform in "darwin-amd64" "darwin-arm64" "linux-amd64" "linux-arm64"; do
|
||||
download_and_extract "${platform}"
|
||||
done
|
||||
|
||||
echo "ESP Clang toolchain completed successfully!"
|
||||
14
.github/workflows/fmt.yml
vendored
14
.github/workflows/fmt.yml
vendored
@@ -2,15 +2,23 @@ name: Format Check
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["**"]
|
||||
branches:
|
||||
- "**"
|
||||
- "!dependabot/**"
|
||||
- "!xgopilot/**"
|
||||
pull_request:
|
||||
branches: ["**"]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
fmt:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Go
|
||||
uses: ./.github/actions/setup-go
|
||||
@@ -21,7 +29,7 @@ jobs:
|
||||
run: |
|
||||
for dir in . runtime; do
|
||||
pushd $dir
|
||||
if [ -n "$(go fmt ./...)" ]; then
|
||||
if [ -n "$(go fmt ./... | grep -v xgo_autogen.go)" ]; then
|
||||
echo "Some files are not properly formatted. Please run 'go fmt ./...'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
14
.github/workflows/go.yml
vendored
14
.github/workflows/go.yml
vendored
@@ -5,22 +5,30 @@ name: Go
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["**"]
|
||||
branches:
|
||||
- "**"
|
||||
- "!dependabot/**"
|
||||
- "!xgopilot/**"
|
||||
pull_request:
|
||||
branches: ["**"]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
continue-on-error: true
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- macos-latest
|
||||
- ubuntu-24.04
|
||||
- ubuntu-latest
|
||||
llvm: [19]
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/setup-deps
|
||||
with:
|
||||
|
||||
93
.github/workflows/llgo.yml
vendored
93
.github/workflows/llgo.yml
vendored
@@ -5,48 +5,78 @@ name: LLGo
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["**"]
|
||||
branches:
|
||||
- "**"
|
||||
- "!dependabot/**"
|
||||
- "!xgopilot/**"
|
||||
pull_request:
|
||||
branches: ["**"]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
download-model:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Download model file
|
||||
run: |
|
||||
mkdir -p ./_demo/llama2-c
|
||||
wget -P ./_demo/llama2-c https://huggingface.co/karpathy/tinyllamas/resolve/main/stories15M.bin
|
||||
mkdir -p ./_demo/c/llama2-c
|
||||
wget -P ./_demo/c/llama2-c https://huggingface.co/karpathy/tinyllamas/resolve/main/stories15M.bin
|
||||
|
||||
- name: Upload model as artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: llama2-model
|
||||
path: ./_demo/llama2-c/stories15M.bin
|
||||
path: ./_demo/c/llama2-c/stories15M.bin
|
||||
retention-days: 1
|
||||
|
||||
llgo:
|
||||
needs: download-model
|
||||
continue-on-error: true
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- macos-latest
|
||||
- ubuntu-24.04
|
||||
- ubuntu-latest
|
||||
llvm: [19]
|
||||
go: ["1.21.13", "1.22.12", "1.23.6", "1.24.2"]
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/setup-deps
|
||||
with:
|
||||
llvm-version: ${{matrix.llvm}}
|
||||
- name: Download model artifact
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: llama2-model
|
||||
path: ./_demo/llama2-c/
|
||||
path: ./_demo/c/llama2-c/
|
||||
- name: Download platform-specific demo libs
|
||||
run: |
|
||||
if ${{ startsWith(matrix.os, 'macos') }}; then
|
||||
DEMO_PKG="cargs_darwin_arm64.zip"
|
||||
else
|
||||
DEMO_PKG="cargs_linux_amd64.zip"
|
||||
fi
|
||||
|
||||
mkdir -p ./_demo/c/cargs/libs
|
||||
cd ./_demo/c/cargs/libs
|
||||
wget https://github.com/goplus/llpkg/releases/download/cargs/v1.0.0/${DEMO_PKG}
|
||||
unzip ${DEMO_PKG}
|
||||
|
||||
# Process pc template files - replace {{.Prefix}} with actual path
|
||||
ACTUAL_PREFIX="$(pwd)"
|
||||
for tmpl in lib/pkgconfig/*.pc.tmpl; do
|
||||
pc_file="${tmpl%.tmpl}"
|
||||
sed "s|{{.Prefix}}|${ACTUAL_PREFIX}|g" "$tmpl" > "$pc_file"
|
||||
done
|
||||
|
||||
echo "PKG_CONFIG_PATH=${ACTUAL_PREFIX}/lib/pkgconfig:${PKG_CONFIG_PATH}" >> $GITHUB_ENV
|
||||
- name: Install further optional dependencies for demos
|
||||
run: |
|
||||
py_deps=(
|
||||
@@ -66,14 +96,21 @@ jobs:
|
||||
echo "LLGO_ROOT=$GITHUB_WORKSPACE" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up Go for testing
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{matrix.go}}
|
||||
|
||||
- name: _xtool build tests
|
||||
- name: Test demo without RPATH (expect failure)
|
||||
run: |
|
||||
cd _xtool
|
||||
llgo build -v ./...
|
||||
echo "Testing demo without RPATH (should fail)..."
|
||||
export LLGO_FULL_RPATH=false
|
||||
pkg-config --libs cargs
|
||||
if (cd ./_demo/c/cargs && llgo run .); then
|
||||
echo "ERROR: cargs demo should have failed without RPATH!"
|
||||
exit 1
|
||||
else
|
||||
echo "✓ cargs demo correctly failed without RPATH"
|
||||
fi
|
||||
|
||||
- name: Test demos
|
||||
run: |
|
||||
@@ -85,9 +122,22 @@ jobs:
|
||||
libdir=$(pkg-config --variable=libdir python-3.12-embed)
|
||||
echo "libdir: $libdir"
|
||||
ln -s $libdir/pkgconfig/python-3.12-embed.pc $pcdir/python3-embed.pc
|
||||
export PKG_CONFIG_PATH=$pcdir
|
||||
export PKG_CONFIG_PATH=$pcdir:${PKG_CONFIG_PATH}
|
||||
export LLGO_FULL_RPATH=true
|
||||
bash .github/workflows/test_demo.sh
|
||||
|
||||
- name: Test C header generation
|
||||
run: |
|
||||
echo "Testing C header generation in different build modes..."
|
||||
cd _demo/go/export
|
||||
chmod +x test.sh
|
||||
./test.sh
|
||||
|
||||
- name: _xtool build tests
|
||||
run: |
|
||||
cd _xtool
|
||||
llgo build -v ./...
|
||||
|
||||
- name: Show test result
|
||||
run: cat result.md
|
||||
|
||||
@@ -99,16 +149,17 @@ jobs:
|
||||
|
||||
test:
|
||||
continue-on-error: true
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- macos-latest
|
||||
- ubuntu-24.04
|
||||
- ubuntu-latest
|
||||
llvm: [19]
|
||||
go: ["1.24.2"]
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/setup-deps
|
||||
with:
|
||||
@@ -132,7 +183,7 @@ jobs:
|
||||
echo "LLGO_ROOT=$GITHUB_WORKSPACE" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up Go for testing
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{matrix.go}}
|
||||
|
||||
@@ -142,14 +193,15 @@ jobs:
|
||||
|
||||
hello:
|
||||
continue-on-error: true
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-24.04, macos-latest]
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
llvm: [19]
|
||||
go: ["1.21.13", "1.22.12", "1.23.6", "1.24.2"]
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/setup-deps
|
||||
with:
|
||||
@@ -200,13 +252,14 @@ jobs:
|
||||
|
||||
cross-compile:
|
||||
continue-on-error: true
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest]
|
||||
llvm: [19]
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/setup-deps
|
||||
with:
|
||||
@@ -233,7 +286,7 @@ jobs:
|
||||
|
||||
- name: Test Cross Compilation (wasm)
|
||||
shell: bash
|
||||
working-directory: _demo
|
||||
working-directory: _demo/c
|
||||
run: |
|
||||
echo "Testing cross-compilation wasm with Go 1.24.2"
|
||||
|
||||
|
||||
40
.github/workflows/populate_darwin_sysroot.sh
vendored
40
.github/workflows/populate_darwin_sysroot.sh
vendored
@@ -1,40 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
TMPDIR="$(mktemp -d)"
|
||||
export TMPDIR
|
||||
trap 'rm -rf "${TMPDIR}"' EXIT
|
||||
|
||||
DARWIN_AMD64_LLVM_PREFIX=.sysroot/darwin/amd64/usr/local/opt/llvm@19
|
||||
DARWIN_ARM64_LLVM_PREFIX=.sysroot/darwin/arm64/opt/homebrew/opt/llvm@19
|
||||
mkdir -p "${DARWIN_AMD64_LLVM_PREFIX}" "${DARWIN_ARM64_LLVM_PREFIX}"
|
||||
|
||||
BREW_LLVM_FORMULA_JSON="$(mktemp)"
|
||||
curl -fsSL https://formulae.brew.sh/api/formula/llvm@19.json > "${BREW_LLVM_FORMULA_JSON}"
|
||||
BREW_LLVM_AMD64_BOTTLE_URL=$(jq -r '.bottle.stable.files.sonoma.url' "${BREW_LLVM_FORMULA_JSON}")
|
||||
BREW_LLVM_ARM64_BOTTLE_URL=$(jq -r '.bottle.stable.files.arm64_sonoma.url' "${BREW_LLVM_FORMULA_JSON}")
|
||||
curl -fsSL -H "Authorization: Bearer QQ==" "${BREW_LLVM_AMD64_BOTTLE_URL}" | tar -xzf - --strip-components=2 -C "${DARWIN_AMD64_LLVM_PREFIX}"
|
||||
curl -fsSL -H "Authorization: Bearer QQ==" "${BREW_LLVM_ARM64_BOTTLE_URL}" | tar -xzf - --strip-components=2 -C "${DARWIN_ARM64_LLVM_PREFIX}"
|
||||
|
||||
patch_homebrew_lib_dir() {
|
||||
local LIB_DIR="$1"
|
||||
local HOMEBREW_PREFIX="$2"
|
||||
for DYLIB_FILE in "${LIB_DIR}"/*.dylib; do
|
||||
if [[ -f "${DYLIB_FILE}" ]]; then
|
||||
ID=$(otool -D "${DYLIB_FILE}" | grep '@@HOMEBREW_PREFIX@@' | awk '{print $1}')
|
||||
if [[ -n "${ID}" ]]; then
|
||||
NEW_ID=${ID/'@@HOMEBREW_PREFIX@@'/${HOMEBREW_PREFIX}}
|
||||
install_name_tool -id "${NEW_ID}" "${DYLIB_FILE}"
|
||||
fi
|
||||
|
||||
DEPS=$(otool -L "${DYLIB_FILE}" | grep '@@HOMEBREW_PREFIX@@' | awk '{print $1}')
|
||||
for DEP in ${DEPS}; do
|
||||
NEW_DEP=${DEP/'@@HOMEBREW_PREFIX@@'/${HOMEBREW_PREFIX}}
|
||||
install_name_tool -change "${DEP}" "${NEW_DEP}" "${DYLIB_FILE}"
|
||||
done
|
||||
fi
|
||||
done
|
||||
}
|
||||
patch_homebrew_lib_dir "${DARWIN_AMD64_LLVM_PREFIX}/lib" /usr/lib
|
||||
patch_homebrew_lib_dir "${DARWIN_ARM64_LLVM_PREFIX}/lib" /opt/homebrew
|
||||
12
.github/workflows/populate_linux_sysroot.sh
vendored
12
.github/workflows/populate_linux_sysroot.sh
vendored
@@ -17,12 +17,7 @@ cat > "${POPULATE_LINUX_SYSROOT_SCRIPT}" << EOF
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
apt-get update
|
||||
apt-get install -y lsb-release gnupg2 wget rsync
|
||||
|
||||
echo "deb http://apt.llvm.org/\$(lsb_release -cs)/ llvm-toolchain-\$(lsb_release -cs)-19 main" | tee /etc/apt/sources.list.d/llvm.list
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
|
||||
apt-get update
|
||||
apt-get install -y llvm-19-dev
|
||||
apt-get install -y build-essential zlib1g-dev rsync
|
||||
|
||||
error() {
|
||||
echo -e "\$1" >&2
|
||||
@@ -139,7 +134,10 @@ populate_linux_sysroot() {
|
||||
/populate_linux_sysroot.sh
|
||||
}
|
||||
populate_linux_sysroot amd64 "${LINUX_AMD64_PREFIX}" &
|
||||
PID1=$!
|
||||
populate_linux_sysroot arm64 "${LINUX_ARM64_PREFIX}" &
|
||||
PID2=$!
|
||||
|
||||
# Wait for both background processes to complete
|
||||
wait
|
||||
wait $PID1 || exit $?
|
||||
wait $PID2 || exit $?
|
||||
|
||||
215
.github/workflows/release-build.yml
vendored
215
.github/workflows/release-build.yml
vendored
@@ -2,51 +2,73 @@ name: Release Build
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
branches:
|
||||
- "**"
|
||||
- "!dependabot/**"
|
||||
- "!xgopilot/**"
|
||||
tags: ["*"]
|
||||
pull_request:
|
||||
branches: ["**"]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
populate-darwin-sysroot:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- name: Populate Darwin sysroot
|
||||
run: bash .github/workflows/populate_darwin_sysroot.sh
|
||||
- name: Create Darwin sysroot tarball
|
||||
run: tar -czvf .sysroot/darwin.tar.gz -C .sysroot darwin
|
||||
- name: Upload Darwin sysroot tarball
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: darwin-sysroot-tarball
|
||||
path: .sysroot/darwin.tar.gz
|
||||
compression-level: 0
|
||||
build:
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
needs: populate-darwin-sysroot
|
||||
outputs:
|
||||
linux-cache-key: ${{ steps.cache-keys.outputs.linux-key }}
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Calculate cache keys
|
||||
id: cache-keys
|
||||
run: |
|
||||
LINUX_KEY="linux-sysroot-${{ hashFiles('.github/workflows/populate_linux_sysroot.sh', '.github/workflows/release-build.yml') }}-v1.0.0"
|
||||
echo "linux-key=$LINUX_KEY" >> $GITHUB_OUTPUT
|
||||
populate-linux-sysroot:
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v5
|
||||
- name: Check Linux sysroot cache
|
||||
id: cache-linux-sysroot
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.24.x
|
||||
path: .sysroot/linux.tar.gz
|
||||
key: ${{ needs.setup.outputs.linux-cache-key }}
|
||||
lookup-only: true
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
if: steps.cache-linux-sysroot.outputs.cache-hit != 'true'
|
||||
with:
|
||||
image: tonistiigi/binfmt:qemu-v7.0.0-28
|
||||
- name: Download Darwin sysroot tarball
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: darwin-sysroot-tarball
|
||||
path: .sysroot
|
||||
- name: Populate Darwin sysroot
|
||||
run: tar -xzvf .sysroot/darwin.tar.gz -C .sysroot
|
||||
- name: Populate Linux sysroot
|
||||
if: steps.cache-linux-sysroot.outputs.cache-hit != 'true'
|
||||
run: bash .github/workflows/populate_linux_sysroot.sh
|
||||
- name: Run GoReleaser
|
||||
- name: Create Linux sysroot tarball
|
||||
if: steps.cache-linux-sysroot.outputs.cache-hit != 'true'
|
||||
run: tar -czvf .sysroot/linux.tar.gz -C .sysroot linux
|
||||
- name: Save Linux sysroot cache
|
||||
if: steps.cache-linux-sysroot.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: .sysroot/linux.tar.gz
|
||||
key: ${{ needs.setup.outputs.linux-cache-key }}
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [setup, populate-linux-sysroot]
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v5
|
||||
- name: Set up Release
|
||||
uses: ./.github/actions/setup-goreleaser
|
||||
with:
|
||||
linux-cache-key: ${{ needs.setup.outputs.linux-cache-key }}
|
||||
- name: Run GoReleaser (Build & Test)
|
||||
env:
|
||||
GITHUB_TOKEN: ${{github.token}}
|
||||
run: |
|
||||
@@ -57,4 +79,129 @@ jobs:
|
||||
-v $(pwd):/go/src/llgo \
|
||||
-w /go/src/llgo \
|
||||
ghcr.io/goreleaser/goreleaser-cross:v1.22 \
|
||||
release --clean --skip nfpm,snapcraft
|
||||
release --verbose --skip=publish,nfpm,snapcraft --snapshot --clean
|
||||
|
||||
- name: Upload Darwin AMD64 Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: llgo-darwin-amd64
|
||||
path: .dist/*darwin-amd64.tar.gz
|
||||
retention-days: 3
|
||||
include-hidden-files: true
|
||||
|
||||
- name: Upload Darwin ARM64 Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: llgo-darwin-arm64
|
||||
path: .dist/*darwin-arm64.tar.gz
|
||||
retention-days: 3
|
||||
include-hidden-files: true
|
||||
|
||||
- name: Upload Linux AMD64 Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: llgo-linux-amd64
|
||||
path: .dist/*linux-amd64.tar.gz
|
||||
retention-days: 3
|
||||
include-hidden-files: true
|
||||
|
||||
- name: Upload Linux ARM64 Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: llgo-linux-arm64
|
||||
path: .dist/*linux-arm64.tar.gz
|
||||
retention-days: 3
|
||||
include-hidden-files: true
|
||||
|
||||
- name: Upload Checksums
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: llgo-checksums
|
||||
path: .dist/*checksums.txt
|
||||
retention-days: 3
|
||||
include-hidden-files: true
|
||||
|
||||
test-artifacts:
|
||||
needs: build
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: macos-15-intel
|
||||
goos: darwin
|
||||
goarch: amd64
|
||||
go-version: "1.24.2"
|
||||
go-mod-version: "1.24"
|
||||
- os: macos-latest
|
||||
goos: darwin
|
||||
goarch: arm64
|
||||
go-version: "1.24.2"
|
||||
go-mod-version: "1.24"
|
||||
- os: ubuntu-latest
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
go-version: "1.24.2"
|
||||
go-mod-version: "1.24"
|
||||
- os: ubuntu-24.04-arm
|
||||
goos: linux
|
||||
goarch: arm64
|
||||
go-version: "1.24.2"
|
||||
go-mod-version: "1.24"
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/setup-deps
|
||||
with:
|
||||
install-llvm: false
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: Download Platform Artifact
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: llgo-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||
path: .
|
||||
|
||||
- name: Extract LLGO Archive
|
||||
run: |
|
||||
echo "Looking for ${{ matrix.goos }}_${{ matrix.goarch }} archive..."
|
||||
ARCHIVE=$(ls *.tar.gz | head -n1)
|
||||
mkdir -p release-llgo
|
||||
tar -xzf "$ARCHIVE" -C release-llgo
|
||||
ls -la release-llgo/
|
||||
echo "${{ github.workspace }}/release-llgo/bin/" >> $GITHUB_PATH
|
||||
|
||||
- name: Test Hello World
|
||||
uses: ./.github/actions/test-helloworld
|
||||
with:
|
||||
go-version: ${{matrix.go-version}}
|
||||
mod-version: ${{ matrix.go-mod-version }}
|
||||
|
||||
release:
|
||||
needs: [setup, test-artifacts, populate-linux-sysroot]
|
||||
runs-on: ubuntu-latest
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Release
|
||||
uses: ./.github/actions/setup-goreleaser
|
||||
with:
|
||||
linux-cache-key: ${{ needs.setup.outputs.linux-cache-key }}
|
||||
- name: Run GoReleaser (Release)
|
||||
env:
|
||||
GITHUB_TOKEN: ${{github.token}}
|
||||
run: |
|
||||
echo "Publishing release for tag: ${{ github.ref }}"
|
||||
echo "All artifact tests passed, proceeding with release..."
|
||||
docker run \
|
||||
--rm \
|
||||
-e GITHUB_TOKEN=${GITHUB_TOKEN} \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v $(pwd):/go/src/llgo \
|
||||
-w /go/src/llgo \
|
||||
ghcr.io/goreleaser/goreleaser-cross:v1.22 \
|
||||
release --clean --verbose --skip nfpm,snapcraft
|
||||
|
||||
48
.github/workflows/targets.yml
vendored
Normal file
48
.github/workflows/targets.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
name: Targets
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
- "!dependabot/**"
|
||||
- "!xgopilot/**"
|
||||
pull_request:
|
||||
branches: ["**"]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
llgo:
|
||||
continue-on-error: true
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- macos-latest
|
||||
- ubuntu-latest
|
||||
llvm: [19]
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/setup-deps
|
||||
with:
|
||||
llvm-version: ${{matrix.llvm}}
|
||||
|
||||
- name: Set up Go for build
|
||||
uses: ./.github/actions/setup-go
|
||||
with:
|
||||
go-version: "1.24.2"
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
go install ./...
|
||||
echo "LLGO_ROOT=$GITHUB_WORKSPACE" >> $GITHUB_ENV
|
||||
|
||||
- name: Build targets
|
||||
run: |
|
||||
cd _demo/embed/targetsbuild
|
||||
bash build.sh
|
||||
4
.github/workflows/test_demo.sh
vendored
4
.github/workflows/test_demo.sh
vendored
@@ -1,11 +1,11 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# llgo run subdirectories under _demo and _pydemo that contain *.go files
|
||||
# llgo run subdirectories under _demo that contain *.go files
|
||||
total=0
|
||||
failed=0
|
||||
failed_cases=""
|
||||
for d in ./_demo/* ./_pydemo/*; do
|
||||
for d in ./_demo/go/* ./_demo/py/* ./_demo/c/*; do
|
||||
if [ -d "$d" ] && [ -n "$(ls "$d"/*.go 2>/dev/null)" ]; then
|
||||
total=$((total+1))
|
||||
echo "Testing $d"
|
||||
|
||||
10
.gitignore
vendored
10
.gitignore
vendored
@@ -7,6 +7,7 @@
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
*.a
|
||||
|
||||
test.db
|
||||
demo.ll
|
||||
@@ -15,6 +16,7 @@ stories*.bin
|
||||
.DS_Store
|
||||
err.log
|
||||
numpy.txt
|
||||
result.txt
|
||||
|
||||
_go/
|
||||
_runtime/
|
||||
@@ -43,3 +45,11 @@ go.work*
|
||||
# GoReleaser
|
||||
.dist/
|
||||
.sysroot/
|
||||
|
||||
# Embedded firmware files
|
||||
*.bin
|
||||
*.hex
|
||||
*.elf
|
||||
*.uf2
|
||||
*.img
|
||||
*.zip
|
||||
|
||||
@@ -23,12 +23,11 @@ builds:
|
||||
ldflags:
|
||||
- -X github.com/goplus/llgo/internal/env.buildVersion=v{{.Version}}
|
||||
- -X github.com/goplus/llgo/internal/env.buildTime={{.Date}}
|
||||
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/local/opt/llvm@19/bin/llvm-config
|
||||
env:
|
||||
- CC=o64-clang
|
||||
- CXX=o64-clang++
|
||||
- CGO_CPPFLAGS=-I{{.Env.SYSROOT_DARWIN_AMD64}}/usr/local/opt/llvm@19/include -mmacosx-version-min=10.13 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
|
||||
- CGO_LDFLAGS=-L{{.Env.SYSROOT_DARWIN_AMD64}}/usr/local/opt/llvm@19/lib -mmacosx-version-min=10.13 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-19 -lz -lm
|
||||
- CGO_CPPFLAGS=-I{{.Env.SYSROOT_DARWIN_AMD64}}/crosscompile/clang/include -mmacosx-version-min=10.13 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
|
||||
- CGO_LDFLAGS=-L{{.Env.SYSROOT_DARWIN_AMD64}}/crosscompile/clang/lib -mmacosx-version-min=10.13 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-19 -lz -lm -Wl,-rpath,@executable_path/../crosscompile/clang/lib
|
||||
targets:
|
||||
- darwin_amd64
|
||||
mod_timestamp: "{{.CommitTimestamp}}"
|
||||
@@ -40,12 +39,11 @@ builds:
|
||||
ldflags:
|
||||
- -X github.com/goplus/llgo/internal/env.buildVersion=v{{.Version}}
|
||||
- -X github.com/goplus/llgo/internal/env.buildTime={{.Date}}
|
||||
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/opt/homebrew/opt/llvm@19/bin/llvm-config
|
||||
env:
|
||||
- CC=oa64-clang
|
||||
- CXX=oa64-clang++
|
||||
- CGO_CPPFLAGS=-I{{.Env.SYSROOT_DARWIN_ARM64}}/opt/homebrew/opt/llvm@19/include -mmacosx-version-min=10.13 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
|
||||
- CGO_LDFLAGS=-L{{.Env.SYSROOT_DARWIN_ARM64}}/opt/homebrew/opt/llvm@19/lib -mmacosx-version-min=10.13 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-19 -lz -lm
|
||||
- CGO_CPPFLAGS=-I{{.Env.SYSROOT_DARWIN_ARM64}}/crosscompile/clang/include -mmacosx-version-min=10.13 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
|
||||
- CGO_LDFLAGS=-L{{.Env.SYSROOT_DARWIN_ARM64}}/crosscompile/clang/lib -mmacosx-version-min=10.13 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-19 -lz -lm -Wl,-rpath,@executable_path/../crosscompile/clang/lib
|
||||
targets:
|
||||
- darwin_arm64
|
||||
mod_timestamp: "{{.CommitTimestamp}}"
|
||||
@@ -57,12 +55,13 @@ builds:
|
||||
ldflags:
|
||||
- -X github.com/goplus/llgo/internal/env.buildVersion=v{{.Version}}
|
||||
- -X github.com/goplus/llgo/internal/env.buildTime={{.Date}}
|
||||
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/lib/llvm-19/bin/llvm-config
|
||||
- "-extldflags=-Wl,-rpath,$ORIGIN/../crosscompile/clang/lib"
|
||||
env:
|
||||
- CC=x86_64-linux-gnu-gcc
|
||||
- CXX=x86_64-linux-gnu-g++
|
||||
- CGO_CPPFLAGS=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -I{{.Env.SYSROOT_LINUX_AMD64}}/usr/include/llvm-19 -I{{.Env.SYSROOT_LINUX_AMD64}}/usr/include/llvm-c-19 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
|
||||
- CGO_LDFLAGS=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -L{{.Env.SYSROOT_LINUX_AMD64}}/usr/lib/llvm-19/lib -lLLVM-19
|
||||
- CGO_CPPFLAGS=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -I{{.Env.SYSROOT_LINUX_AMD64}}/crosscompile/clang/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
|
||||
- CGO_LDFLAGS=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -L{{.Env.SYSROOT_LINUX_AMD64}}/crosscompile/clang/lib -L{{.Env.SYSROOT_LINUX_AMD64}}/lib/x86_64-linux-gnu -lLLVM-19 -lz
|
||||
- CGO_LDFLAGS_ALLOW=--sysroot.*
|
||||
targets:
|
||||
- linux_amd64
|
||||
mod_timestamp: "{{.CommitTimestamp}}"
|
||||
@@ -74,12 +73,13 @@ builds:
|
||||
ldflags:
|
||||
- -X github.com/goplus/llgo/internal/env.buildVersion=v{{.Version}}
|
||||
- -X github.com/goplus/llgo/internal/env.buildTime={{.Date}}
|
||||
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/lib/llvm-19/bin/llvm-config
|
||||
- "-extldflags=-Wl,-rpath,$ORIGIN/../crosscompile/clang/lib"
|
||||
env:
|
||||
- CC=aarch64-linux-gnu-gcc
|
||||
- CXX=aarch64-linux-gnu-g++
|
||||
- CGO_CPPFLAGS=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -I{{.Env.SYSROOT_LINUX_ARM64}}/usr/include/llvm-19 -I{{.Env.SYSROOT_LINUX_ARM64}}/usr/include/llvm-c-19 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
|
||||
- CGO_LDFLAGS=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -L{{.Env.SYSROOT_LINUX_ARM64}}/usr/lib/llvm-19/lib -lLLVM-19
|
||||
- CGO_CPPFLAGS=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -I{{.Env.SYSROOT_LINUX_ARM64}}/crosscompile/clang/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
|
||||
- CGO_LDFLAGS=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -L{{.Env.SYSROOT_LINUX_ARM64}}/crosscompile/clang/lib -L{{.Env.SYSROOT_LINUX_ARM64}}/lib/aarch64-linux-gnu -lLLVM-19 -lz
|
||||
- CGO_LDFLAGS_ALLOW=--sysroot.*
|
||||
targets:
|
||||
- linux_arm64
|
||||
mod_timestamp: "{{.CommitTimestamp}}"
|
||||
@@ -93,7 +93,11 @@ archives:
|
||||
- LICENSE
|
||||
- README.md
|
||||
- runtime
|
||||
|
||||
- targets
|
||||
- src: ".sysroot/{{.Os}}/{{.Arch}}/crosscompile/clang"
|
||||
dst: crosscompile/clang
|
||||
info:
|
||||
mode: 0755
|
||||
checksum:
|
||||
name_template: "{{.ProjectName}}{{.Version}}.checksums.txt"
|
||||
|
||||
@@ -104,9 +108,9 @@ nfpms:
|
||||
maintainer: Aofei Sheng <aofei@aofeisheng.com>
|
||||
description: |
|
||||
LLGo is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python. It's a
|
||||
subproject of the Go+ project.
|
||||
subproject of the XGo project.
|
||||
|
||||
LLGo aims to expand the boundaries of Go/Go+, providing limitless possibilities such as:
|
||||
LLGo aims to expand the boundaries of Go/XGo, providing limitless possibilities such as:
|
||||
|
||||
- Game development
|
||||
- AI and data science
|
||||
@@ -128,9 +132,9 @@ snapcrafts:
|
||||
summary: A Go compiler based on LLVM
|
||||
description: |
|
||||
LLGo is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python. It's a
|
||||
subproject of the Go+ project.
|
||||
subproject of the XGo project.
|
||||
|
||||
LLGo aims to expand the boundaries of Go/Go+, providing limitless possibilities such as:
|
||||
LLGo aims to expand the boundaries of Go/XGo, providing limitless possibilities such as:
|
||||
|
||||
- Game development
|
||||
- AI and data science
|
||||
|
||||
132
CLAUDE.md
Normal file
132
CLAUDE.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# LLGo Project AI Assistant Guide
|
||||
|
||||
This document provides essential information for AI assistants to help fix bugs and implement features in the LLGo project.
|
||||
|
||||
## About LLGo
|
||||
|
||||
LLGo is a Go compiler based on LLVM designed to better integrate Go with the C ecosystem, including Python and JavaScript. It's a subproject of the XGo project that aims to expand the boundaries of Go/XGo for game development, AI and data science, WebAssembly, and embedded development.
|
||||
|
||||
## Project Structure
|
||||
|
||||
- `cmd/llgo` - Main llgo compiler command (usage similar to `go` command)
|
||||
- `cl/` - Core compiler logic that converts Go packages to LLVM IR
|
||||
- `ssa/` - LLVM IR file generation using Go SSA semantics
|
||||
- `internal/build/` - Build process orchestration
|
||||
- `runtime/` - LLGo runtime library
|
||||
- `chore/` - Development tools (llgen, llpyg, ssadump, etc.)
|
||||
- `_demo/` - Example programs demonstrating C/C++ interop (`c/hello`, `c/qsort`) and Python integration (`py/callpy`, `py/numpy`)
|
||||
- `_cmptest/` - Comparison tests to verify the same program gets the same output with Go and LLGo
|
||||
|
||||
## Development Environment
|
||||
|
||||
For detailed dependency requirements and installation instructions, see the [Dependencies](README.md#dependencies) and [How to install](README.md#how-to-install) sections in the README.
|
||||
|
||||
## Testing & Validation
|
||||
|
||||
The following commands and workflows are essential when fixing bugs or implementing features in the LLGo project:
|
||||
|
||||
### Run all tests
|
||||
```bash
|
||||
go test ./...
|
||||
```
|
||||
|
||||
**Note:** Some tests may fail if optional dependencies (like Python) are not properly configured. The test suite includes comprehensive tests for:
|
||||
- Compiler functionality
|
||||
- SSA generation
|
||||
- C interop
|
||||
- Python integration (requires Python development headers)
|
||||
|
||||
### Write and run tests for your changes
|
||||
|
||||
When adding new functionality or fixing bugs, create appropriate test cases:
|
||||
|
||||
```bash
|
||||
# Add your test to the relevant package's *_test.go file
|
||||
# Then run tests for that package
|
||||
go test ./path/to/package
|
||||
|
||||
# Or run all tests
|
||||
go test ./...
|
||||
```
|
||||
|
||||
**Important:** The `LLGO_ROOT` environment variable must be set to the repository root when running llgo commands during development.
|
||||
|
||||
## Code Quality
|
||||
|
||||
Before submitting any code updates, you must run the following formatting and validation commands:
|
||||
|
||||
### Format code
|
||||
```bash
|
||||
go fmt ./...
|
||||
```
|
||||
|
||||
**Important:** Always run `go fmt ./...` before committing code changes. This ensures consistent code formatting across the project.
|
||||
|
||||
### Run static analysis
|
||||
```bash
|
||||
go vet ./...
|
||||
```
|
||||
|
||||
**Note:** Currently reports some issues related to lock passing by value in `ssa/type_cvt.go` and a possible unsafe.Pointer misuse in `cl/builtin_test.go`. These are known issues.
|
||||
|
||||
|
||||
## Common Development Tasks
|
||||
|
||||
### Build the entire project
|
||||
```bash
|
||||
go build -v ./...
|
||||
```
|
||||
|
||||
### Build llgo command specifically
|
||||
```bash
|
||||
go build -o llgo ./cmd/llgo
|
||||
```
|
||||
|
||||
### Check llgo version
|
||||
```bash
|
||||
llgo version
|
||||
```
|
||||
|
||||
### Install llgo for system-wide use
|
||||
```bash
|
||||
./install.sh
|
||||
```
|
||||
|
||||
### Build development tools
|
||||
```bash
|
||||
go install -v ./cmd/...
|
||||
go install -v ./chore/...
|
||||
```
|
||||
|
||||
## Key Modules for Understanding
|
||||
|
||||
- `ssa` - Generates LLVM IR using Go SSA semantics
|
||||
- `cl` - Core compiler converting Go to LLVM IR
|
||||
- `internal/build` - Orchestrates the compilation process
|
||||
|
||||
## Debugging
|
||||
|
||||
### Disable Garbage Collection
|
||||
For testing purposes, you can disable GC:
|
||||
```bash
|
||||
LLGO_ROOT=/path/to/llgo llgo run -tags nogc .
|
||||
```
|
||||
|
||||
## LLGO_ROOT Environment Variable
|
||||
|
||||
**CRITICAL:** Always set `LLGO_ROOT` to the repository root when running llgo during development:
|
||||
|
||||
```bash
|
||||
export LLGO_ROOT=/path/to/llgo
|
||||
# or
|
||||
LLGO_ROOT=/path/to/llgo llgo run .
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
|
||||
1. **Testing Requirement:** All bug fixes and features MUST include tests
|
||||
2. **Demo Directory:** Examples in `_demo` are prefixed with `_` to prevent standard `go` command from trying to compile them
|
||||
3. **Defer in Loops:** LLGo intentionally does not support `defer` in loops (considered bad practice)
|
||||
4. **C Ecosystem Integration:** LLGo uses `go:linkname` directive to link external symbols through ABI
|
||||
5. **Python Integration:** Third-party Python libraries require separate installation of library files
|
||||
|
||||
55
README.md
55
README.md
@@ -6,11 +6,11 @@ llgo - A Go compiler based on LLVM
|
||||
[](https://github.com/goplus/llgo/releases)
|
||||
[](https://codecov.io/gh/goplus/llgo)
|
||||
[](https://pkg.go.dev/github.com/goplus/llgo)
|
||||
[](https://github.com/goplus/gop)
|
||||
[](https://github.com/goplus/gop)
|
||||
|
||||
LLGo is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python. It's a subproject of [the Go+ project](https://github.com/goplus/gop).
|
||||
LLGo is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python and JavaScript. It's a subproject of [the XGo project](https://github.com/goplus/gop).
|
||||
|
||||
LLGo aims to expand the boundaries of Go/Go+, providing limitless possibilities such as:
|
||||
LLGo aims to expand the boundaries of Go/XGo, providing limitless possibilities such as:
|
||||
|
||||
* Game development
|
||||
* AI and data science
|
||||
@@ -21,10 +21,10 @@ LLGo aims to expand the boundaries of Go/Go+, providing limitless possibilities
|
||||
How can these be achieved?
|
||||
|
||||
```
|
||||
LLGo := Go + C + Python
|
||||
LLGo := Go * C ecosystem
|
||||
```
|
||||
|
||||
LLGo is compatible with C and Python through the language's **Application Binary Interface (ABI)**, while LLGo is compatible with Go through its **syntax (source code)**. And here C doesn't just include C, but all languages that are ABI compatible with C, including C/C++, Objective-C, Swift, etc.
|
||||
LLGo is compatible with C ecosystem through the language's **Application Binary Interface (ABI)**, while LLGo is compatible with Go through its **syntax (source code)**. C ecosystem includes all languages that are ABI compatible with C (eg. C/C++, Python, JavaScript, Objective-C, Swift, etc).
|
||||
|
||||
|
||||
## C/C++ standard libary support
|
||||
@@ -63,14 +63,14 @@ This is a simple example of calling the C `printf` function to print `Hello worl
|
||||
|
||||
The `_demo` directory contains some C standard libary related demos (it start with `_` to prevent the `go` command from compiling it):
|
||||
|
||||
* [hello](_demo/hello/hello.go): call C `printf` to print `Hello world`
|
||||
* [concat](_demo/concat/concat.go): call C `fprintf` with `stderr`
|
||||
* [qsort](_demo/qsort/qsort.go): call C function with a callback (eg. `qsort`)
|
||||
* [hello](_demo/c/hello/hello.go): call C `printf` to print `Hello world`
|
||||
* [concat](_demo/c/concat/concat.go): call C `fprintf` with `stderr`
|
||||
* [qsort](_demo/c/qsort/qsort.go): call C function with a callback (eg. `qsort`)
|
||||
|
||||
To run these demos (If you haven't installed `llgo` yet, please refer to [How to install](#how-to-install)):
|
||||
|
||||
```sh
|
||||
cd <demo-directory> # eg. cd _demo/hello
|
||||
cd <demo-directory> # eg. cd _demo/c/hello
|
||||
llgo run .
|
||||
```
|
||||
|
||||
@@ -88,7 +88,7 @@ import _ "unsafe" // for go:linkname
|
||||
func Sqrt(x float64) float64
|
||||
```
|
||||
|
||||
You can directly integrate it into [your own code](_demo/linkname/linkname.go):
|
||||
You can directly integrate it into [your own code](_demo/c/linkname/linkname.go):
|
||||
|
||||
<!-- embedme doc/_readme/llgo_call_c/call_c.go -->
|
||||
|
||||
@@ -204,17 +204,17 @@ func main() {
|
||||
|
||||
Here we define two 3x3 matrices a and b, add them to get x, and then print the result.
|
||||
|
||||
The `_pydemo` directory contains some python related demos:
|
||||
The `_demo/py/` directory contains some python related demos:
|
||||
|
||||
* [callpy](_pydemo/callpy/callpy.go): call Python standard library function `math.sqrt`
|
||||
* [pi](_pydemo/pi/pi.go): print python constants `math.pi`
|
||||
* [statistics](_pydemo/statistics/statistics.go): define a python list and call `statistics.mean` to get the mean
|
||||
* [matrix](_pydemo/matrix/matrix.go): a basic `numpy` demo
|
||||
* [callpy](_demo/py/callpy/callpy.go): call Python standard library function `math.sqrt`
|
||||
* [pi](_demo/py/pi/pi.go): print python constants `math.pi`
|
||||
* [statistics](_demo/py/statistics/statistics.go): define a python list and call `statistics.mean` to get the mean
|
||||
* [matrix](_demo/py/matrix/matrix.go): a basic `numpy` demo
|
||||
|
||||
To run these demos (If you haven't installed `llgo` yet, please refer to [How to install](#how-to-install)):
|
||||
|
||||
```sh
|
||||
cd <demo-directory> # eg. cd _pydemo/callpy
|
||||
cd <demo-directory> # eg. cd _demo/py/callpy
|
||||
llgo run .
|
||||
```
|
||||
|
||||
@@ -242,7 +242,7 @@ The currently supported libraries include:
|
||||
|
||||
Here are some examples related to them:
|
||||
|
||||
* [llama2-c](_demo/llama2-c): inference Llama 2 (It's the first llgo AI example)
|
||||
* [llama2-c](_demo/c/llama2-c): inference Llama 2 (It's the first llgo AI example)
|
||||
* [mkjson](https://github.com/goplus/lib/tree/main/c/cjson/_demo/mkjson/mkjson.go): create a json object and print it
|
||||
* [sqlitedemo](https://github.com/goplus/lib/tree/main/c/sqlite/_demo/sqlitedemo/demo.go): a basic sqlite demo
|
||||
* [tetris](https://github.com/goplus/lib/tree/main/c/raylib/_demo/tetris/tetris.go): a tetris game based on raylib
|
||||
@@ -252,11 +252,11 @@ Here are some examples related to them:
|
||||
|
||||
All Go syntax (including `cgo`) is already supported. Here are some examples:
|
||||
|
||||
* [concat](_demo/concat/concat.go): define a variadic function
|
||||
* [genints](_demo/genints/genints.go): various forms of closure usage (including C function, recv.method and anonymous function)
|
||||
* [concat](_demo/c/concat/concat.go): define a variadic function
|
||||
* [genints](_demo/c/genints/genints.go): various forms of closure usage (including C function, recv.method and anonymous function)
|
||||
* [errors](_cmptest/errors/errors.go): demo to implement error interface
|
||||
* [defer](_cmptest/defer/defer.go): defer demo
|
||||
* [goroutine](_demo/goroutine/goroutine.go): goroutine demo
|
||||
* [goroutine](_demo/go/goroutine/goroutine.go): goroutine demo
|
||||
|
||||
|
||||
### Defer
|
||||
@@ -323,6 +323,7 @@ Here are the Go packages that can be imported correctly:
|
||||
* [hash/adler32](https://pkg.go.dev/hash/adler32)
|
||||
* [hash/crc32](https://pkg.go.dev/hash/crc32) (partially)
|
||||
* [hash/crc64](https://pkg.go.dev/hash/crc64)
|
||||
* [hash/maphash](https://pkg.go.dev/hash/maphash) (partially)
|
||||
* [crypto](https://pkg.go.dev/crypto)
|
||||
* [crypto/md5](https://pkg.go.dev/crypto/md5)
|
||||
* [crypto/sha1](https://pkg.go.dev/crypto/sha1)
|
||||
@@ -335,6 +336,7 @@ Here are the Go packages that can be imported correctly:
|
||||
* [regexp/syntax](https://pkg.go.dev/regexp/syntax)
|
||||
* [go/token](https://pkg.go.dev/go/token)
|
||||
* [go/scanner](https://pkg.go.dev/go/scanner)
|
||||
* [go/parser](https://pkg.go.dev/go/parser)
|
||||
|
||||
|
||||
## Dependencies
|
||||
@@ -376,7 +378,7 @@ brew link --overwrite llvm@19 lld@19 libffi
|
||||
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-19 main" | sudo tee /etc/apt/sources.list.d/llvm.list
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y llvm-19-dev clang-19 libclang-19-dev lld-19 pkg-config libgc-dev libssl-dev zlib1g-dev libcjson-dev libsqlite3-dev libunwind-dev libuv1-dev
|
||||
sudo apt-get install -y llvm-19-dev clang-19 libclang-19-dev lld-19 libunwind-19-dev libc++-19-dev pkg-config libgc-dev libssl-dev zlib1g-dev libcjson-dev libsqlite3-dev libuv1-dev
|
||||
sudo apt-get install -y python3.12-dev # optional
|
||||
#curl https://raw.githubusercontent.com/goplus/llgo/refs/heads/main/install.sh | bash
|
||||
./install.sh
|
||||
@@ -385,16 +387,23 @@ sudo apt-get install -y python3.12-dev # optional
|
||||
#### Alpine Linux
|
||||
|
||||
```sh
|
||||
apk add go llvm18-dev clang18-dev lld18 pkgconf gc-dev openssl-dev zlib-dev
|
||||
apk add go llvm19-dev clang19-dev lld19 pkgconf gc-dev libunwind-dev openssl-dev zlib-dev
|
||||
apk add python3-dev # optional
|
||||
apk add g++ # build only
|
||||
export LLVM_CONFIG=/usr/lib/llvm18/bin/llvm-config
|
||||
export LLVM_CONFIG=/usr/lib/llvm19/bin/llvm-config
|
||||
export CGO_CPPFLAGS="$($LLVM_CONFIG --cppflags)"
|
||||
export CGO_CXXFLAGS=-std=c++17
|
||||
export CGO_LDFLAGS="$($LLVM_CONFIG --ldflags) $($LLVM_CONFIG --libs all)"
|
||||
curl https://raw.githubusercontent.com/goplus/llgo/refs/heads/main/install.sh | bash
|
||||
```
|
||||
|
||||
docker alpine 386 llgo environment
|
||||
```
|
||||
export GCC_ROOT_DIR=$(gcc -print-search-dirs | grep 'install:' | awk -F': ' '{print $2}')
|
||||
export LDFLAGS="-L$GCC_ROOT_DIR -B$GCC_ROOT_DIR -Wl,-dynamic-linker,/lib/ld-musl-i386.so.1"
|
||||
llgo run .
|
||||
```
|
||||
|
||||
### on Windows
|
||||
|
||||
TODO
|
||||
|
||||
33
_cmptest/_goconstdemo/goconst.go
Normal file
33
_cmptest/_goconstdemo/goconst.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Create the complex number 2.3 + 5i.
|
||||
ar := constant.MakeFloat64(2.3)
|
||||
ai := constant.MakeImag(constant.MakeInt64(5))
|
||||
a := constant.BinaryOp(ar, token.ADD, ai)
|
||||
|
||||
// Compute (2.3 + 5i) * 11.
|
||||
b := constant.MakeUint64(11)
|
||||
c := constant.BinaryOp(a, token.MUL, b)
|
||||
|
||||
// Convert c into a complex128.
|
||||
Ar, exact := constant.Float64Val(constant.Real(c))
|
||||
if !exact {
|
||||
fmt.Printf("Could not represent real part %s exactly as float64\n", constant.Real(c))
|
||||
}
|
||||
Ai, exact := constant.Float64Val(constant.Imag(c))
|
||||
if !exact {
|
||||
fmt.Printf("Could not represent imaginary part %s as exactly as float64\n", constant.Imag(c))
|
||||
}
|
||||
C := complex(Ar, Ai)
|
||||
|
||||
fmt.Println("literal", 25.3+55i)
|
||||
fmt.Println("go/constant", c)
|
||||
fmt.Println("complex128", C)
|
||||
}
|
||||
71
_cmptest/issue961/typeconv.go
Normal file
71
_cmptest/issue961/typeconv.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
// Test 1: int8 overflow wrapping
|
||||
var i8max int8 = 127
|
||||
fmt.Printf("int8(127) + 1 = %d\n", i8max+1)
|
||||
|
||||
// Test 2: int8 arithmetic edge cases
|
||||
var a int8 = 100
|
||||
var b int8 = 50
|
||||
fmt.Printf("int8(100) + int8(50) = %d\n", a+b)
|
||||
|
||||
// Test 3: int8 multiplication overflow
|
||||
var m int8 = 64
|
||||
fmt.Printf("int8(64) * 2 = %d\n", m*2)
|
||||
|
||||
// Test 4: uint32 to float64 to int32 conversion
|
||||
var bigUint32 uint32 = 0xFFFFFFFF
|
||||
fmt.Printf("int32(float64(uint32(0xFFFFFFFF))) = %d\n", int32(float64(bigUint32)))
|
||||
|
||||
// Test 5: untyped constant with typed variable
|
||||
const untypedInt = 42
|
||||
var i32 int32 = 70000
|
||||
fmt.Printf("const(42) + int32(70000) = %d\n", untypedInt+i32)
|
||||
|
||||
// Test 6: signed to unsigned conversion
|
||||
var negInt int32 = -1
|
||||
fmt.Printf("uint32(int32(-1)) = 0x%X\n", uint32(negInt))
|
||||
|
||||
// Test 7: unsigned to signed conversion
|
||||
var bigUint uint32 = 0xFFFFFFFF
|
||||
fmt.Printf("int32(uint32(0xFFFFFFFF)) = %d\n", int32(bigUint))
|
||||
|
||||
// Test 8: sign extension
|
||||
var i8 int8 = -1
|
||||
fmt.Printf("int32(int8(-1)) = %d\n", int32(i8))
|
||||
|
||||
// Test 9: truncation
|
||||
var i64 int64 = 0x123456789ABC
|
||||
fmt.Printf("int32(int64(0x123456789ABC)) = 0x%X\n", uint32(int32(i64)))
|
||||
|
||||
// Test 10: more overflow cases
|
||||
var i8min int8 = -128
|
||||
fmt.Printf("int8(-128) - 1 = %d\n", i8min-1)
|
||||
|
||||
var u8max uint8 = 255
|
||||
fmt.Printf("uint8(255) + 1 = %d\n", u8max+1)
|
||||
|
||||
// Test 11: negation overflow
|
||||
var n1 int8 = -128
|
||||
fmt.Printf("-int8(-128) = %d\n", -n1)
|
||||
|
||||
// Test 12: division edge case
|
||||
var d1 int8 = -128
|
||||
var d2 int8 = -1
|
||||
fmt.Printf("int8(-128) / int8(-1) = %d\n", d1/d2)
|
||||
|
||||
// Test 13: int16 overflow
|
||||
var i16max int16 = 32767
|
||||
fmt.Printf("int16(32767) + 1 = %d\n", i16max+1)
|
||||
|
||||
// Test 14: uint8 truncation from int32
|
||||
var negInt8 int32 = -1
|
||||
fmt.Printf("uint8(int32(-1)) = 0x%X\n", uint8(negInt8))
|
||||
|
||||
// Test 15: zero extension
|
||||
var u8 uint8 = 0xFF
|
||||
fmt.Printf("uint32(uint8(0xFF)) = 0x%X\n", uint32(u8))
|
||||
}
|
||||
25
_cmptest/mathbigdemo/big.go
Normal file
25
_cmptest/mathbigdemo/big.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Initialize two big ints with the first two numbers in the sequence.
|
||||
a := big.NewInt(0)
|
||||
b := big.NewInt(1)
|
||||
|
||||
// Initialize limit as 10^99, the smallest integer with 100 digits.
|
||||
var limit big.Int
|
||||
limit.Exp(big.NewInt(10), big.NewInt(99), nil)
|
||||
|
||||
// Loop while a is smaller than 1e100.
|
||||
for a.Cmp(&limit) < 0 {
|
||||
// Compute the next Fibonacci number, storing it in a.
|
||||
a.Add(a, b)
|
||||
// Swap a and b so that b is the next number in the sequence.
|
||||
a, b = b, a
|
||||
}
|
||||
fmt.Println(a) // 100-digit Fibonacci number
|
||||
}
|
||||
18
_demo/c/asmcall/asmcall.go
Normal file
18
_demo/c/asmcall/asmcall.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
//llgo:link asm llgo.asm
|
||||
func asm(instruction string) {}
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
for i := 0; i < 100000; i++ {
|
||||
asm("nop")
|
||||
}
|
||||
duration := time.Since(start)
|
||||
fmt.Println("Duration:", duration)
|
||||
}
|
||||
21
_demo/c/asmfullcall/asmfullcall.go
Normal file
21
_demo/c/asmfullcall/asmfullcall.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
//llgo:link asmFull llgo.asm
|
||||
func asmFull(instruction string, regs map[string]any) uintptr { return 0 }
|
||||
|
||||
var testVar = 0
|
||||
|
||||
func main() {
|
||||
verify()
|
||||
}
|
||||
|
||||
func check(expected, actual int) {
|
||||
if expected != actual {
|
||||
panic(fmt.Sprintf("Expected: %d, Got: %d\n", expected, actual))
|
||||
}
|
||||
fmt.Println("asm check passed:", actual)
|
||||
}
|
||||
31
_demo/c/asmfullcall/asmfullcall_darwin.go
Normal file
31
_demo/c/asmfullcall/asmfullcall_darwin.go
Normal file
@@ -0,0 +1,31 @@
|
||||
//go:build darwin && arm64
|
||||
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func verify() {
|
||||
// 0 output & 0 input
|
||||
asmFull("nop", nil)
|
||||
|
||||
// 0 output & 1 input with memory address
|
||||
addr := uintptr(unsafe.Pointer(&testVar))
|
||||
asmFull("str {value}, [{addr}]", map[string]any{
|
||||
"addr": addr,
|
||||
"value": 43,
|
||||
})
|
||||
check(43, testVar)
|
||||
|
||||
// 1 output & 1 input
|
||||
res1 := asmFull("mov {}, {value}", map[string]any{
|
||||
"value": 41,
|
||||
})
|
||||
check(41, int(res1))
|
||||
|
||||
// 1 output & 2 inputs
|
||||
res2 := asmFull("add {}, {a}, {b}", map[string]any{
|
||||
"a": 25,
|
||||
"b": 17,
|
||||
})
|
||||
check(42, int(res2))
|
||||
}
|
||||
30
_demo/c/asmfullcall/asmfullcall_linux.go
Normal file
30
_demo/c/asmfullcall/asmfullcall_linux.go
Normal file
@@ -0,0 +1,30 @@
|
||||
//go:build linux && amd64
|
||||
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func verify() {
|
||||
// 0 output & 0 input
|
||||
asmFull("nop", nil)
|
||||
|
||||
// 0 output & 1 input with memory address
|
||||
addr := uintptr(unsafe.Pointer(&testVar))
|
||||
asmFull("movq {value}, ({addr})", map[string]any{
|
||||
"addr": addr,
|
||||
"value": 43,
|
||||
})
|
||||
check(43, testVar)
|
||||
|
||||
// 1 output & 1 input
|
||||
res1 := asmFull("movq {value}, {}", map[string]any{
|
||||
"value": 41,
|
||||
})
|
||||
check(41, int(res1))
|
||||
|
||||
res2 := asmFull("leaq ({a},{b}), {}", map[string]any{
|
||||
"a": 25,
|
||||
"b": 17,
|
||||
})
|
||||
check(42, int(res2))
|
||||
}
|
||||
395
_demo/c/cabi/main.go
Normal file
395
_demo/c/cabi/main.go
Normal file
@@ -0,0 +1,395 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
LLGoFiles = "wrap/wrap.c"
|
||||
)
|
||||
|
||||
type point struct {
|
||||
x int32
|
||||
y int32
|
||||
}
|
||||
|
||||
//go:linkname pt C.pt
|
||||
func pt(pt point) point
|
||||
|
||||
type point1 struct {
|
||||
x int32
|
||||
y int32
|
||||
z int32
|
||||
}
|
||||
|
||||
//go:linkname pt1 C.pt1
|
||||
func pt1(pt point1) point1
|
||||
|
||||
type point2 struct {
|
||||
x int8
|
||||
y int32
|
||||
z int32
|
||||
}
|
||||
|
||||
//go:linkname pt2 C.pt2
|
||||
func pt2(pt point2) point2
|
||||
|
||||
type point3 struct {
|
||||
x int8
|
||||
y int8
|
||||
z int8
|
||||
}
|
||||
|
||||
//go:linkname pt3 C.pt3
|
||||
func pt3(pt point3) point3
|
||||
|
||||
type point4 struct {
|
||||
x int8
|
||||
y int8
|
||||
z int8
|
||||
m int32
|
||||
}
|
||||
|
||||
//go:linkname pt4 C.pt4
|
||||
func pt4(pt point4) point4
|
||||
|
||||
type point5 struct {
|
||||
x int8
|
||||
y int8
|
||||
z int8
|
||||
m int8
|
||||
n int8
|
||||
}
|
||||
|
||||
//go:linkname pt5 C.pt5
|
||||
func pt5(pt point5) point5
|
||||
|
||||
type point6 struct {
|
||||
x int8
|
||||
y int8
|
||||
z int8
|
||||
m int8
|
||||
n int8
|
||||
k int32
|
||||
}
|
||||
|
||||
//go:linkname pt6 C.pt6
|
||||
func pt6(pt point6) point6
|
||||
|
||||
type point7 struct {
|
||||
x int8
|
||||
y int8
|
||||
z int8
|
||||
m int8
|
||||
n int8
|
||||
k int32
|
||||
o int8
|
||||
}
|
||||
|
||||
//go:linkname pt7 C.pt7
|
||||
func pt7(pt point7) point7
|
||||
|
||||
type data1 struct {
|
||||
x int8
|
||||
y int64
|
||||
}
|
||||
|
||||
//go:linkname fn1 C.fn1
|
||||
func fn1(data1) data1
|
||||
|
||||
type data2 struct {
|
||||
x int32
|
||||
y int64
|
||||
}
|
||||
|
||||
//go:linkname fn2 C.fn2
|
||||
func fn2(data2) data2
|
||||
|
||||
type data3 struct {
|
||||
x int64
|
||||
y int8
|
||||
}
|
||||
|
||||
//go:linkname fn3 C.fn3
|
||||
func fn3(data3) data3
|
||||
|
||||
type fdata1 struct {
|
||||
x float32
|
||||
}
|
||||
|
||||
//go:linkname ff1 C.ff1
|
||||
func ff1(fdata1) fdata1
|
||||
|
||||
type fdata2 struct {
|
||||
x float32
|
||||
y float32
|
||||
}
|
||||
|
||||
//go:linkname ff2 C.ff2
|
||||
func ff2(fdata2) fdata2
|
||||
|
||||
type fdata2i struct {
|
||||
x float32
|
||||
y int32
|
||||
}
|
||||
|
||||
//go:linkname ff2i C.ff2i
|
||||
func ff2i(fdata2i) fdata2i
|
||||
|
||||
type fdata3 struct {
|
||||
x float32
|
||||
y float32
|
||||
z float32
|
||||
}
|
||||
|
||||
//go:linkname ff3 C.ff3
|
||||
func ff3(fdata3) fdata3
|
||||
|
||||
type fdata4 struct {
|
||||
x float32
|
||||
y float32
|
||||
z float32
|
||||
m float32
|
||||
}
|
||||
|
||||
//go:linkname ff4 C.ff4
|
||||
func ff4(fdata4) fdata4
|
||||
|
||||
type fdata5 struct {
|
||||
x float32
|
||||
y float32
|
||||
z float32
|
||||
m float32
|
||||
n float32
|
||||
}
|
||||
|
||||
//go:linkname ff5 C.ff5
|
||||
func ff5(fdata5) fdata5
|
||||
|
||||
type fdata2id struct {
|
||||
x int8
|
||||
y int8
|
||||
z float64
|
||||
}
|
||||
|
||||
//go:linkname ff2id C.ff2id
|
||||
func ff2id(fdata2id) fdata2id
|
||||
|
||||
type fdata7if struct {
|
||||
x [7]int8
|
||||
y float32
|
||||
}
|
||||
|
||||
//go:linkname ff7if C.ff7if
|
||||
func ff7if(fdata7if) fdata7if
|
||||
|
||||
type fdata4if struct {
|
||||
x float32
|
||||
y int8
|
||||
z float32
|
||||
m float32
|
||||
}
|
||||
|
||||
//go:linkname ff4if C.ff4if
|
||||
func ff4if(fdata4if) fdata4if
|
||||
|
||||
type array struct {
|
||||
x [8]int32
|
||||
}
|
||||
|
||||
//go:linkname demo64 C.demo64
|
||||
func demo64(n int64) int64
|
||||
|
||||
//go:linkname demo32 C.demo32
|
||||
func demo32(n int32) int32
|
||||
|
||||
type struct32 struct {
|
||||
v int32
|
||||
}
|
||||
|
||||
//go:linkname demo32s C.demo32s
|
||||
func demo32s(v struct32) struct32
|
||||
|
||||
type point64 struct {
|
||||
x int64
|
||||
y int64
|
||||
}
|
||||
|
||||
//go:linkname pt64 C.pt64
|
||||
func pt64(pt point64) point64
|
||||
|
||||
//go:linkname demo C.demo
|
||||
func demo(a array) array
|
||||
|
||||
//go:linkname demo2 C.demo2
|
||||
func demo2(x int32) array
|
||||
|
||||
type ddata1 struct {
|
||||
x float64
|
||||
}
|
||||
|
||||
//go:linkname dd1 C.dd1
|
||||
func dd1(d ddata1) ddata1
|
||||
|
||||
type ddata2 struct {
|
||||
x float64
|
||||
y float64
|
||||
}
|
||||
|
||||
//go:linkname dd2 C.dd2
|
||||
func dd2(d ddata2) ddata2
|
||||
|
||||
type ddata3 struct {
|
||||
x float64
|
||||
y float64
|
||||
z float64
|
||||
}
|
||||
|
||||
//go:linkname dd3 C.dd3
|
||||
func dd3(d ddata3) ddata3
|
||||
|
||||
//llgo:type C
|
||||
type Callback func(array, point, point1) array
|
||||
|
||||
//go:linkname callback C.callback
|
||||
func callback(fn Callback, ar array)
|
||||
|
||||
//llgo:type C
|
||||
type Callback1 func(array, point, point1) point
|
||||
|
||||
//go:linkname callback1 C.callback1
|
||||
func callback1(fn Callback1, ar array)
|
||||
|
||||
//go:linkname mycallback C.mycallback
|
||||
func mycallback(ar array, pt point, pt1 point1) point
|
||||
|
||||
func myfn1(ar array, pt point, pt1 point1) point {
|
||||
println("=>", ar.x[0], ar.x[1], ar.x[7], pt.x, pt.y, pt1.x, pt1.y, pt1.z)
|
||||
return point{100, 200}
|
||||
}
|
||||
|
||||
//export export_demo
|
||||
func export_demo(ar array) array {
|
||||
println("=> export", ar.x[0], ar.x[1], ar.x[7])
|
||||
return ar
|
||||
}
|
||||
|
||||
func main() {
|
||||
cabi_demo()
|
||||
callback_demo()
|
||||
}
|
||||
|
||||
func callback_demo() {
|
||||
export_demo(array{x: [8]int32{1, 2, 3, 4, 5, 6, 7, 8}})
|
||||
|
||||
callback(func(ar array, pt point, pt1 point1) array {
|
||||
println("=> callback", ar.x[0], ar.x[1], ar.x[7], pt.x, pt.y, pt1.x, pt1.y, pt1.z)
|
||||
return array{x: [8]int32{8, 7, 6, 5, 4, 3, 2, 1}}
|
||||
}, array{x: [8]int32{1, 2, 3, 4, 5, 6, 7, 8}})
|
||||
|
||||
callback1(func(ar array, pt point, pt1 point1) point {
|
||||
println("=> callback1", ar.x[0], ar.x[1], ar.x[7], pt.x, pt.y, pt1.x, pt1.y, pt1.z)
|
||||
return point{100, 200}
|
||||
}, array{x: [8]int32{1, 2, 3, 4, 5, 6, 7, 8}})
|
||||
ret := mycallback(array{x: [8]int32{1, 2, 3, 4, 5, 6, 7, 8}}, point{1, 2}, point1{1, 2, 3})
|
||||
println("=> mycallback", ret.x, ret.y)
|
||||
callback1(myfn1, array{x: [8]int32{1, 2, 3, 4, 5, 6, 7, 8}})
|
||||
callback1(myfn1, array{x: [8]int32{8, 7, 6, 5, 4, 3, 2, 1}})
|
||||
callback1(mycallback, array{x: [8]int32{10, 20, 30, 40, 50, 60, 70, 80}})
|
||||
}
|
||||
|
||||
func cabi_demo() {
|
||||
i32 := demo32(1024)
|
||||
println("=> demo32", i32)
|
||||
|
||||
s32 := demo32s(struct32{100})
|
||||
println("=> demo32s", s32.v)
|
||||
|
||||
i64 := demo64(1024)
|
||||
println("=> demo64", i64)
|
||||
|
||||
p64 := pt64(point64{1024, -1024})
|
||||
println("=> pt64", p64.x, p64.y)
|
||||
|
||||
r := demo(array{x: [8]int32{1, 2, 3, 4, 5, 6, 7, 8}})
|
||||
println("=> demo", r.x[0], r.x[1])
|
||||
|
||||
r2 := demo2(100)
|
||||
println("=> demo2", r2.x[0], r2.x[1], r2.x[7])
|
||||
|
||||
p0 := pt(point{1, 2})
|
||||
println("=> pt0", p0.x, p0.y)
|
||||
|
||||
p1 := pt1(point1{1, 2, 3})
|
||||
println("=> pt1", p1.x, p1.y, p1.z)
|
||||
|
||||
p2 := pt2(point2{1, 2, 3})
|
||||
println("=> pt2", p2.x, p2.y, p2.z)
|
||||
|
||||
p3 := pt3(point3{1, 2, 3})
|
||||
println("=> pt3", p3.x, p3.y, p3.z)
|
||||
|
||||
p4 := pt4(point4{1, 2, 3, 4})
|
||||
println("=> pt4", p4.x, p4.y, p4.z, p4.m)
|
||||
|
||||
p5 := pt5(point5{1, 2, 3, 4, 5})
|
||||
println("=> pt5", p5.x, p5.y, p5.z, p5.m, p5.n)
|
||||
|
||||
p6 := pt6(point6{1, 2, 3, 4, 5, 6})
|
||||
println("=> pt6", p6.x, p6.y, p6.z, p6.m, p6.n, p6.k)
|
||||
|
||||
p7 := pt7(point7{1, 2, 3, 4, 5, 6, 7})
|
||||
println("=> pt7", p7.x, p7.y, p7.z, p7.m, p7.n, p7.k, p7.o)
|
||||
|
||||
// skip wrap
|
||||
fd1 := fn1(data1{1, 2})
|
||||
println("=> fd1", fd1.x, fd1.y)
|
||||
|
||||
fd2 := fn2(data2{1, 2})
|
||||
println("=> fd2", fd2.x, fd2.y)
|
||||
|
||||
fd3 := fn3(data3{1, 2})
|
||||
println("=> fd3", fd3.x, fd3.y)
|
||||
|
||||
// float
|
||||
f1 := ff1(fdata1{1.1})
|
||||
println("=> f1", f1.x)
|
||||
|
||||
// float
|
||||
f2 := ff2(fdata2{1.1, 2.1})
|
||||
println("=> f2", f2.x, f2.y)
|
||||
|
||||
// float
|
||||
f2i := ff2i(fdata2i{1.1, 2})
|
||||
println("=> f2i", f2i.x, f2i.y)
|
||||
|
||||
// float
|
||||
f3 := ff3(fdata3{1.1, 2.1, 3.1})
|
||||
println("=> f3", f3.x, f3.y, f3.z)
|
||||
|
||||
// float
|
||||
f4 := ff4(fdata4{1.1, 2.1, 3.1, 4.1})
|
||||
println("=> f4", f4.x, f4.y, f4.z, f4.m)
|
||||
|
||||
// float
|
||||
f5 := ff5(fdata5{1.1, 2.1, 3.1, 4.1, 5.1})
|
||||
println("=> f5", f5.x, f5.y, f5.z, f5.m, f5.n)
|
||||
|
||||
f2id := ff2id(fdata2id{1, 2, 3.1})
|
||||
println("=> f2id", f2id.x, f2id.y, f2id.z)
|
||||
|
||||
f7if := ff7if(fdata7if{[7]int8{1, 2, 3, 4, 5, 6, 7}, 3.1})
|
||||
println("=> f7if", f7if.x[0], f7if.x[1], f7if.y)
|
||||
|
||||
f4if := ff4if(fdata4if{1.1, 2, 3.1, 4.1})
|
||||
println("=> f4if", f4if.x, f4if.y, f4if.z, f4if.m)
|
||||
|
||||
d1 := dd1(ddata1{1.1})
|
||||
println("=> dd1", d1.x)
|
||||
|
||||
d2 := dd2(ddata2{1.1, 2.1})
|
||||
println("=> dd2", d2.x, d2.y)
|
||||
|
||||
d3 := dd3(ddata3{1.1, 2.1, 3.1})
|
||||
println("=> dd3", d3.x, d3.y, d3.z)
|
||||
}
|
||||
325
_demo/c/cabi/wrap/wrap.c
Normal file
325
_demo/c/cabi/wrap/wrap.c
Normal file
@@ -0,0 +1,325 @@
|
||||
extern int printf(const char *format, ...);
|
||||
|
||||
int demo32(int v) {
|
||||
return v+100;
|
||||
}
|
||||
|
||||
long long demo64(long long v) {
|
||||
return v+100;
|
||||
}
|
||||
|
||||
struct struct32 {
|
||||
int v;
|
||||
};
|
||||
|
||||
struct point64 {
|
||||
long long x;
|
||||
long long y;
|
||||
};
|
||||
|
||||
struct point64 pt64(struct point64 pt) {
|
||||
printf("point64: %lld %lld\n",pt.x,pt.y);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct struct32 demo32s(struct struct32 v) {
|
||||
printf("struct32: %d\n",v.v);
|
||||
struct struct32 v2 = {v.v+100};
|
||||
return v2;
|
||||
}
|
||||
|
||||
struct point {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
struct point pt(struct point pt) {
|
||||
printf("point: %d %d\n",pt.x,pt.y);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct point1 {
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
};
|
||||
|
||||
struct point1 pt1(struct point1 pt) {
|
||||
printf("point1: %d %d %d\n",pt.x,pt.y,pt.z);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct point2 {
|
||||
char x;
|
||||
int y;
|
||||
int z;
|
||||
};
|
||||
|
||||
struct point2 pt2(struct point2 pt) {
|
||||
printf("point2: %d %d %d\n",pt.x,pt.y,pt.z);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct point3 {
|
||||
char x;
|
||||
char y;
|
||||
char z;
|
||||
};
|
||||
|
||||
struct point3 pt3(struct point3 pt) {
|
||||
printf("point3: %d %d %d\n",pt.x,pt.y,pt.z);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct point4 {
|
||||
char x;
|
||||
char y;
|
||||
char z;
|
||||
int m;
|
||||
};
|
||||
|
||||
struct point4 pt4(struct point4 pt) {
|
||||
printf("point4: %d %d %d %d\n",pt.x,pt.y,pt.z,pt.m);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct point5 {
|
||||
char x;
|
||||
char y;
|
||||
char z;
|
||||
char m;
|
||||
char n;
|
||||
};
|
||||
|
||||
struct point5 pt5(struct point5 pt) {
|
||||
printf("point5: %d %d %d %d %d\n",pt.x,pt.y,pt.z,pt.m,pt.n);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct point6 {
|
||||
char x;
|
||||
char y;
|
||||
char z;
|
||||
char m;
|
||||
char n;
|
||||
int k;
|
||||
};
|
||||
|
||||
struct point6 pt6(struct point6 pt) {
|
||||
printf("point6: %d %d %d %d %d %d\n",pt.x,pt.y,pt.z,pt.m,pt.n,pt.k);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct point7 {
|
||||
char x;
|
||||
char y;
|
||||
char z;
|
||||
char m;
|
||||
char n;
|
||||
int k;
|
||||
char o;
|
||||
};
|
||||
|
||||
struct point7 pt7(struct point7 pt) {
|
||||
printf("point7: %d %d %d %d %d %d %d\n",pt.x,pt.y,pt.z,pt.m,pt.n,pt.k,pt.o);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct data1 {
|
||||
char x;
|
||||
long long y;
|
||||
};
|
||||
|
||||
struct data1 fn1(struct data1 pt) {
|
||||
printf("data1: %d %lld\n",pt.x,pt.y);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct data2 {
|
||||
int x;
|
||||
long long y;
|
||||
};
|
||||
|
||||
struct data2 fn2(struct data2 pt) {
|
||||
printf("data2: %d %lld\n",pt.x,pt.y);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct data3 {
|
||||
long long x;
|
||||
char y;
|
||||
};
|
||||
|
||||
struct data3 fn3(struct data3 pt) {
|
||||
printf("data3: %lld %d\n",pt.x,pt.y);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct fdata1 {
|
||||
float x;
|
||||
};
|
||||
|
||||
struct fdata1 ff1(struct fdata1 pt) {
|
||||
printf("ff1: %f\n",pt.x);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct ddata1 {
|
||||
double x;
|
||||
};
|
||||
|
||||
struct ddata1 dd1(struct ddata1 pt) {
|
||||
printf("dd1: %f\n",pt.x);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct ddata2 {
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
struct ddata2 dd2(struct ddata2 pt) {
|
||||
printf("dd2: %f %f\n",pt.x,pt.y);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct ddata3 {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct ddata3 dd3(struct ddata3 pt) {
|
||||
printf("dd3: %f %f %f\n",pt.x,pt.y,pt.z);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct fdata2i {
|
||||
float x;
|
||||
int y;
|
||||
};
|
||||
|
||||
struct fdata2i ff2i(struct fdata2i pt) {
|
||||
printf("ff2i: %f %d\n",pt.x,pt.y);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct fdata2 {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
struct fdata2 ff2(struct fdata2 pt) {
|
||||
printf("ff2: %f %f\n",pt.x,pt.y);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct fdata3 {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
struct fdata3 ff3(struct fdata3 pt) {
|
||||
printf("ff3: %f %f %f\n",pt.x,pt.y,pt.z);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct fdata4 {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float m;
|
||||
};
|
||||
|
||||
struct fdata4 ff4(struct fdata4 pt) {
|
||||
printf("ff4: %f %f %f %f\n",pt.x,pt.y,pt.z,pt.m);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct fdata5 {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float m;
|
||||
float n;
|
||||
};
|
||||
|
||||
struct fdata5 ff5(struct fdata5 pt) {
|
||||
printf("ff5: %f %f %f %f %f\n",pt.x,pt.y,pt.z,pt.m,pt.n);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct fdata2id {
|
||||
char x;
|
||||
char y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct fdata2id ff2id(struct fdata2id pt) {
|
||||
printf("ff6: %d %d %f\n",pt.x,pt.y,pt.z);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct fdata7if {
|
||||
char x[7];
|
||||
float z;
|
||||
};
|
||||
|
||||
struct fdata7if ff7if(struct fdata7if pt) {
|
||||
printf("ff7if: %d %d %f\n",pt.x[0],pt.x[1],pt.z);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct fdata4if {
|
||||
float x;
|
||||
char y;
|
||||
float z;
|
||||
float m;
|
||||
};
|
||||
|
||||
struct fdata4if ff4if(struct fdata4if pt) {
|
||||
printf("ff4if: %f %d %f %f\n",pt.x,pt.y,pt.z,pt.m);
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct array {
|
||||
int x[8];
|
||||
};
|
||||
|
||||
struct array demo(struct array a) {
|
||||
printf("demo: %d %d %d\n",a.x[0],a.x[1],a.x[2]);
|
||||
return a;
|
||||
}
|
||||
|
||||
struct array demo2(int a1){
|
||||
struct array x;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
x.x[i] = i+a1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
void callback(struct array (*fn)(struct array ar, struct point pt, struct point1 pt1), struct array ar) {
|
||||
demo(ar);
|
||||
struct point pt = {1,2};
|
||||
struct point1 pt1 = {1,2,3};
|
||||
struct array ret = fn(ar,pt,pt1);
|
||||
demo(ret);
|
||||
}
|
||||
|
||||
void callback1(struct point (*fn)(struct array ar, struct point pt, struct point1 pt1), struct array ar) {
|
||||
printf("callback1 array: %d %d %d\n",ar.x[0],ar.x[1],ar.x[7]);
|
||||
struct point pt = {1,2};
|
||||
struct point1 pt1 = {1,2,3};
|
||||
struct point ret = fn(ar,pt,pt1);
|
||||
printf("callback1 ret: %d,%d\n",ret.x,ret.y);
|
||||
}
|
||||
|
||||
struct point mycallback(struct array ar, struct point pt, struct point1 pt1) {
|
||||
printf("mycallback array: %d %d %d\n",ar.x[0],ar.x[1],ar.x[7]);
|
||||
printf("mycallback pt: %d %d\n",pt.x,pt.y);
|
||||
printf("mycallback pt1: %d %d %d\n",pt1.x,pt1.y,pt1.z);
|
||||
struct point ret = {pt.x+pt1.x, pt.y+pt1.y};
|
||||
return ret;
|
||||
}
|
||||
39
_demo/c/cabisret/main.go
Normal file
39
_demo/c/cabisret/main.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package main
|
||||
|
||||
type array9 struct {
|
||||
x [9]float32
|
||||
}
|
||||
|
||||
func demo1(a array9) array9 {
|
||||
a.x[0] += 1
|
||||
return a
|
||||
}
|
||||
|
||||
func demo2(a array9) array9 {
|
||||
for i := 0; i < 1024*128; i++ {
|
||||
a = demo1(a)
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func testDemo() {
|
||||
ar := array9{x: [9]float32{1, 2, 3, 4, 5, 6, 7, 8, 9}}
|
||||
for i := 0; i < 1024*128; i++ {
|
||||
ar = demo1(ar)
|
||||
}
|
||||
ar = demo2(ar)
|
||||
println(ar.x[0], ar.x[1])
|
||||
}
|
||||
|
||||
func testSlice() {
|
||||
var b []byte
|
||||
for i := 0; i < 1024*128; i++ {
|
||||
b = append(b, byte(i))
|
||||
}
|
||||
_ = b
|
||||
}
|
||||
|
||||
func main() {
|
||||
testDemo()
|
||||
testSlice()
|
||||
}
|
||||
144
_demo/c/cargs/demo.go
Normal file
144
_demo/c/cargs/demo.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/lib/c"
|
||||
)
|
||||
|
||||
const LLGoPackage string = "link: $(pkg-config --libs cargs);"
|
||||
|
||||
type Option struct {
|
||||
Identifier c.Char
|
||||
AccessLetters *c.Char
|
||||
AccessName *c.Char
|
||||
ValueName *c.Char
|
||||
Description *c.Char
|
||||
}
|
||||
|
||||
type OptionContext struct {
|
||||
Options *Option
|
||||
OptionCount c.SizeT
|
||||
Argc c.Int
|
||||
Argv **c.Char
|
||||
Index c.Int
|
||||
InnerIndex c.Int
|
||||
ErrorIndex c.Int
|
||||
ErrorLetter c.Char
|
||||
ForcedEnd bool
|
||||
Identifier c.Char
|
||||
Value *c.Char
|
||||
}
|
||||
|
||||
// llgo:type C
|
||||
type Printer func(__llgo_arg_0 c.Pointer, __llgo_arg_1 *c.Char, __llgo_va_list ...interface{}) c.Int
|
||||
|
||||
// llgo:link (*OptionContext).OptionInit C.cag_option_init
|
||||
func (recv_ *OptionContext) OptionInit(options *Option, option_count c.SizeT, argc c.Int, argv **c.Char) {
|
||||
}
|
||||
|
||||
// llgo:link (*OptionContext).OptionFetch C.cag_option_fetch
|
||||
func (recv_ *OptionContext) OptionFetch() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// llgo:link (*OptionContext).OptionGetIdentifier C.cag_option_get_identifier
|
||||
func (recv_ *OptionContext) OptionGetIdentifier() c.Char {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*OptionContext).OptionGetValue C.cag_option_get_value
|
||||
func (recv_ *OptionContext) OptionGetValue() *c.Char {
|
||||
return nil
|
||||
}
|
||||
|
||||
// llgo:link (*OptionContext).OptionGetIndex C.cag_option_get_index
|
||||
func (recv_ *OptionContext) OptionGetIndex() c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*OptionContext).OptionGetErrorIndex C.cag_option_get_error_index
|
||||
func (recv_ *OptionContext) OptionGetErrorIndex() c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*OptionContext).OptionGetErrorLetter C.cag_option_get_error_letter
|
||||
func (recv_ *OptionContext) OptionGetErrorLetter() c.Char {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*OptionContext).OptionPrintError C.cag_option_print_error
|
||||
func (recv_ *OptionContext) OptionPrintError(destination *c.FILE) {
|
||||
}
|
||||
|
||||
// llgo:link (*OptionContext).OptionPrinterError C.cag_option_printer_error
|
||||
func (recv_ *OptionContext) OptionPrinterError(printer Printer, printer_ctx c.Pointer) {
|
||||
}
|
||||
|
||||
// llgo:link (*Option).OptionPrint C.cag_option_print
|
||||
func (recv_ *Option) OptionPrint(option_count c.SizeT, destination *c.FILE) {
|
||||
}
|
||||
|
||||
// llgo:link (*Option).OptionPrinter C.cag_option_printer
|
||||
func (recv_ *Option) OptionPrinter(option_count c.SizeT, printer Printer, printer_ctx c.Pointer) {
|
||||
}
|
||||
|
||||
// llgo:link (*OptionContext).OptionPrepare C.cag_option_prepare
|
||||
func (recv_ *OptionContext) OptionPrepare(options *Option, option_count c.SizeT, argc c.Int, argv **c.Char) {
|
||||
}
|
||||
|
||||
// llgo:link (*OptionContext).OptionGet C.cag_option_get
|
||||
func (recv_ *OptionContext) OptionGet() c.Char {
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
options := []Option{
|
||||
{
|
||||
Identifier: 'h',
|
||||
AccessLetters: c.Str("h"),
|
||||
AccessName: c.Str("help"),
|
||||
ValueName: nil,
|
||||
Description: c.Str("Show help information"),
|
||||
},
|
||||
{
|
||||
Identifier: 'v',
|
||||
AccessLetters: c.Str("v"),
|
||||
AccessName: c.Str("version"),
|
||||
ValueName: nil,
|
||||
Description: c.Str("Show version information"),
|
||||
},
|
||||
}
|
||||
|
||||
args := os.Args
|
||||
|
||||
// Convert Go string array to C-style argv
|
||||
argv := make([]*int8, len(args))
|
||||
for i, arg := range args {
|
||||
argv[i] = c.AllocaCStr(arg)
|
||||
}
|
||||
|
||||
// Initialize option context
|
||||
var context OptionContext
|
||||
context.OptionInit(&options[0], uintptr(len(options)), c.Int(len(args)), &argv[0])
|
||||
|
||||
// Process all options
|
||||
identifierFound := false
|
||||
for context.OptionFetch() {
|
||||
identifierFound = true
|
||||
identifier := context.OptionGetIdentifier()
|
||||
switch identifier {
|
||||
case 'h':
|
||||
fmt.Println("Help: This is a simple command-line parser demo")
|
||||
case 'v':
|
||||
fmt.Println("Version: 1.0.0")
|
||||
}
|
||||
}
|
||||
|
||||
// Default output if no identifier is found
|
||||
if !identifierFound {
|
||||
fmt.Println("Demo Command-line Tool\nIdentifier:\n\t-h: Help\n\t-v: Version")
|
||||
}
|
||||
}
|
||||
@@ -106,8 +106,8 @@ import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/_demo/cgofull/pymod1"
|
||||
"github.com/goplus/llgo/_demo/cgofull/pymod2"
|
||||
"github.com/goplus/llgo/_demo/c/cgofull/pymod1"
|
||||
"github.com/goplus/llgo/_demo/c/cgofull/pymod2"
|
||||
)
|
||||
|
||||
//export go_callback_not_use_in_go
|
||||
@@ -3,7 +3,7 @@ package main
|
||||
import (
|
||||
"github.com/goplus/lib/c"
|
||||
"github.com/goplus/lib/c/math"
|
||||
"github.com/goplus/llgo/_demo/cppintf/foo"
|
||||
"github.com/goplus/llgo/_demo/c/cppintf/foo"
|
||||
)
|
||||
|
||||
type Bar struct {
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/goplus/lib/c"
|
||||
"github.com/goplus/lib/c/math"
|
||||
"github.com/goplus/llgo/_demo/cppmintf/foo"
|
||||
"github.com/goplus/llgo/_demo/c/cppmintf/foo"
|
||||
)
|
||||
|
||||
type Bar struct {
|
||||
12
_demo/c/cppstr/cppstr.go
Normal file
12
_demo/c/cppstr/cppstr.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/goplus/lib/c"
|
||||
"github.com/goplus/lib/cpp/std"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := std.Str("Hello world\n")
|
||||
c.Printf(s.CStr())
|
||||
print(s.Str(), s.Size(), "\n")
|
||||
}
|
||||
5
_demo/c/go.mod
Normal file
5
_demo/c/go.mod
Normal file
@@ -0,0 +1,5 @@
|
||||
module github.com/goplus/llgo/_demo/c
|
||||
|
||||
go 1.20
|
||||
|
||||
require github.com/goplus/lib v0.3.0
|
||||
2
_demo/c/go.sum
Normal file
2
_demo/c/go.sum
Normal file
@@ -0,0 +1,2 @@
|
||||
github.com/goplus/lib v0.3.0 h1:y0ZGb5Q/RikW1oMMB4Di7XIZIpuzh/7mlrR8HNbxXCA=
|
||||
github.com/goplus/lib v0.3.0/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0=
|
||||
@@ -11,7 +11,3 @@ func main() {
|
||||
fmt.Println("hello world by fmt.Println")
|
||||
c.Printf(c.Str("Hello world by c.Printf\n"))
|
||||
}
|
||||
|
||||
/* Expected output:
|
||||
Hello world
|
||||
*/
|
||||
|
Before Width: | Height: | Size: 183 KiB After Width: | Height: | Size: 183 KiB |
@@ -36,7 +36,6 @@ loop: // parse command line arguments
|
||||
// build the Tokenizer via the tokenizer .bin file
|
||||
var tokenizer llama2.Tokenizer
|
||||
llama2.BuildTokenizer(&tokenizer, tokenizerPath, transformer.Config.VocabSize)
|
||||
|
||||
// build the Sampler
|
||||
var sampler llama2.Sampler
|
||||
llama2.BuildSampler(&sampler, transformer.Config.VocabSize, temperature, topp, rngSeed)
|
||||
16
_demo/embed/esp32/hello/main.go
Normal file
16
_demo/embed/esp32/hello/main.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import "github.com/goplus/lib/c"
|
||||
|
||||
func myprint(s *c.Char) {
|
||||
for i := 0; i < int(c.Strlen(s)); i++ {
|
||||
WriteByte(byte(c.Index(s, i)))
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
for {
|
||||
myprint(c.Str("hello world"))
|
||||
sleep(1)
|
||||
}
|
||||
}
|
||||
13
_demo/embed/esp32/hello/uart.go
Normal file
13
_demo/embed/esp32/hello/uart.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/lib/c"
|
||||
)
|
||||
|
||||
//go:linkname WriteByte C.board_uart_write_char
|
||||
func WriteByte(b byte)
|
||||
|
||||
//go:linkname sleep sleep
|
||||
func sleep(c c.Int)
|
||||
1162
_demo/embed/esp32/libc/main.go
Normal file
1162
_demo/embed/esp32/libc/main.go
Normal file
File diff suppressed because it is too large
Load Diff
385
_demo/embed/esp32/rt/main.go
Normal file
385
_demo/embed/esp32/rt/main.go
Normal file
@@ -0,0 +1,385 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/llgo/_demo/embed/esp32/watchdog"
|
||||
)
|
||||
|
||||
//
|
||||
//go:linkname absvdi2 __absvdi2
|
||||
func absvdi2(a int64) int64
|
||||
|
||||
//go:linkname absvsi2 __absvsi2
|
||||
func absvsi2(a int32) int32
|
||||
|
||||
//go:linkname adddf3 __adddf3
|
||||
func adddf3(a, b float64) float64
|
||||
|
||||
//go:linkname addsf3 __addsf3
|
||||
func addsf3(a, b float32) float32
|
||||
|
||||
//go:linkname addvdi3 __addvdi3
|
||||
func addvdi3(a, b int64) int64
|
||||
|
||||
//go:linkname addvsi3 __addvsi3
|
||||
func addvsi3(a, b int32) int32
|
||||
|
||||
//go:linkname udivdi3 __udivdi3
|
||||
func udivdi3(a, b uint64) uint64
|
||||
|
||||
//go:linkname clzdi2 __clzdi2
|
||||
func clzdi2(a uint64) int32
|
||||
|
||||
//go:linkname clzsi2 __clzsi2
|
||||
func clzsi2(a uint32) int32
|
||||
|
||||
//go:linkname ctzdi2 __ctzdi2
|
||||
func ctzdi2(a uint64) int32
|
||||
|
||||
//go:linkname ctzsi2 __ctzsi2
|
||||
func ctzsi2(a uint32) int32
|
||||
|
||||
//go:linkname popcountdi2 __popcountdi2
|
||||
func popcountdi2(a uint64) int32
|
||||
|
||||
//go:linkname popcountsi2 __popcountsi2
|
||||
func popcountsi2(a uint32) int32
|
||||
|
||||
//go:linkname divdf3 __divdf3
|
||||
func divdf3(a, b float64) float64
|
||||
|
||||
//go:linkname divsf3 __divsf3
|
||||
func divsf3(a, b float32) float32
|
||||
|
||||
//go:linkname mulsf3 __mulsf3
|
||||
func mulsf3(a, b float32) float32
|
||||
|
||||
//go:linkname divdi3 __divdi3
|
||||
func divdi3(a, b int64) int64
|
||||
|
||||
//go:linkname muldf3 __muldf3
|
||||
func muldf3(a, b float64) float64
|
||||
|
||||
//go:linkname muldi3 __muldi3
|
||||
func muldi3(a, b int64) int64
|
||||
|
||||
//go:linkname subdf3 __subdf3
|
||||
func subdf3(a, b float64) float64
|
||||
|
||||
//go:linkname subsf3 __subsf3
|
||||
func subsf3(a, b float32) float32
|
||||
|
||||
//go:linkname extendsfdf2 __extendsfdf2
|
||||
func extendsfdf2(a float32) float64
|
||||
|
||||
//go:linkname fixdfdi __fixdfdi
|
||||
func fixdfdi(a float64) int64
|
||||
|
||||
//go:linkname fixdfsi __fixdfsi
|
||||
func fixdfsi(a float64) int32
|
||||
|
||||
//go:linkname fixsfdi __fixsfdi
|
||||
func fixsfdi(a float32) int64
|
||||
|
||||
//go:linkname fixsfsi __fixsfsi
|
||||
func fixsfsi(a float32) int32
|
||||
|
||||
//go:linkname floatdidf __floatdidf
|
||||
func floatdidf(a int64) float64
|
||||
|
||||
//go:linkname floatsidf __floatsidf
|
||||
func floatsidf(a int32) float64
|
||||
|
||||
//go:linkname ashldi3 __ashldi3
|
||||
func ashldi3(a int64, b int32) int64
|
||||
|
||||
//go:linkname ashrdi3 __ashrdi3
|
||||
func ashrdi3(a int64, b int32) int64
|
||||
|
||||
//go:linkname lshrdi3 __lshrdi3
|
||||
func lshrdi3(a uint64, b int32) uint64
|
||||
|
||||
//go:linkname bswapdi2 __bswapdi2
|
||||
func bswapdi2(a uint64) uint64
|
||||
|
||||
//go:linkname bswapsi2 __bswapsi2
|
||||
func bswapsi2(a uint32) uint32
|
||||
|
||||
var totalTests = 0
|
||||
var passedTests = 0
|
||||
var failedTests = 0
|
||||
|
||||
func assertEqualInt32(name string, actual, expected int32) {
|
||||
totalTests++
|
||||
if actual != expected {
|
||||
println("FAIL: %s: expected %d, got %d\n", name, expected, actual)
|
||||
failedTests++
|
||||
} else {
|
||||
passedTests++
|
||||
}
|
||||
}
|
||||
|
||||
func assertEqualInt64(name string, actual, expected int64) {
|
||||
totalTests++
|
||||
if actual != expected {
|
||||
println("FAIL: %s: expected %d, got %d\n", name, expected, actual)
|
||||
failedTests++
|
||||
} else {
|
||||
passedTests++
|
||||
}
|
||||
}
|
||||
|
||||
func assertEqualUint32(name string, actual, expected uint32) {
|
||||
totalTests++
|
||||
if actual != expected {
|
||||
println("FAIL: %s: expected %d, got %d\n", name, expected, actual)
|
||||
failedTests++
|
||||
} else {
|
||||
passedTests++
|
||||
}
|
||||
}
|
||||
|
||||
func assertEqualUint64(name string, actual, expected uint64) {
|
||||
totalTests++
|
||||
if actual != expected {
|
||||
println("FAIL: %s: expected %d, got %d\n", name, expected, actual)
|
||||
failedTests++
|
||||
} else {
|
||||
passedTests++
|
||||
}
|
||||
}
|
||||
|
||||
func assertEqualFloat32(name string, actual, expected float32, epsilon float32) {
|
||||
totalTests++
|
||||
diff := actual - expected
|
||||
if diff < 0 {
|
||||
diff = -diff
|
||||
}
|
||||
if diff > epsilon {
|
||||
println("FAIL: %s: expected %f, got %f\n", name, expected, actual)
|
||||
failedTests++
|
||||
} else {
|
||||
passedTests++
|
||||
}
|
||||
}
|
||||
|
||||
func assertEqualFloat64(name string, actual, expected float64, epsilon float64) {
|
||||
totalTests++
|
||||
diff := actual - expected
|
||||
if diff < 0 {
|
||||
diff = -diff
|
||||
}
|
||||
if diff > epsilon {
|
||||
println("FAIL: %s: expected %f, got %f\n", name, expected, actual)
|
||||
failedTests++
|
||||
} else {
|
||||
passedTests++
|
||||
}
|
||||
}
|
||||
|
||||
func testAbsFunctions() {
|
||||
println("Testing absolute value functions...")
|
||||
|
||||
// Test absvsi2
|
||||
assertEqualInt32("absvsi2", absvsi2(12345), 12345)
|
||||
assertEqualInt32("absvsi2", absvsi2(-12345), 12345)
|
||||
assertEqualInt32("absvsi2", absvsi2(0), 0)
|
||||
|
||||
// Test absvdi2
|
||||
assertEqualInt64("absvdi2", absvdi2(1234567890123456789), 1234567890123456789)
|
||||
assertEqualInt64("absvdi2", absvdi2(-1234567890123456789), 1234567890123456789)
|
||||
assertEqualInt64("absvdi2", absvdi2(0), 0)
|
||||
}
|
||||
|
||||
func testAddFunctions() {
|
||||
println("Testing addition functions...")
|
||||
|
||||
// Test addvsi3
|
||||
assertEqualInt32("addvsi3", addvsi3(1000, 2000), 3000)
|
||||
assertEqualInt32("addvsi3", addvsi3(-1000, -2000), -3000)
|
||||
assertEqualInt32("addvsi3", addvsi3(0, 0), 0)
|
||||
|
||||
// Test addvdi3
|
||||
assertEqualInt64("addvdi3", addvdi3(1000000000, 2000000000), 3000000000)
|
||||
assertEqualInt64("addvdi3", addvdi3(-1000000000, -2000000000), -3000000000)
|
||||
assertEqualInt64("addvdi3", addvdi3(0, 0), 0)
|
||||
|
||||
// Test adddf3
|
||||
assertEqualFloat64("adddf3", adddf3(3.14, 2.71), 5.85, 1e-10)
|
||||
assertEqualFloat64("adddf3", adddf3(-3.14, -2.71), -5.85, 1e-10)
|
||||
assertEqualFloat64("adddf3", adddf3(0.0, 0.0), 0.0, 1e-10)
|
||||
|
||||
// Test addsf3
|
||||
assertEqualFloat32("addsf3", addsf3(3.14, 2.71), 5.85, 1e-6)
|
||||
assertEqualFloat32("addsf3", addsf3(-3.14, -2.71), -5.85, 1e-6)
|
||||
assertEqualFloat32("addsf3", addsf3(0.0, 0.0), 0.0, 1e-6)
|
||||
}
|
||||
|
||||
func testCountFunctions() {
|
||||
println("Testing count functions...")
|
||||
|
||||
// Test clzsi2 - count leading zeros in 32-bit integer
|
||||
assertEqualInt32("clzsi2", clzsi2(1), 31) // 0x00000001 has 31 leading zeros
|
||||
assertEqualInt32("clzsi2", clzsi2(0x80000000), 0) // 0x80000000 has 0 leading zeros
|
||||
assertEqualInt32("clzsi2", clzsi2(0), 32) // 0 has 32 leading zeros
|
||||
|
||||
// FIXME
|
||||
// // Test clzdi2 - count leading zeros in 64-bit integer
|
||||
// assertEqualInt32("clzdi2", clzdi2(1), 63) // 0x0000000000000001 has 63 leading zeros
|
||||
// assertEqualInt32("clzdi2", clzdi2(0x8000000000000000), 0) // 0x8000000000000000 has 0 leading zeros
|
||||
// assertEqualInt32("clzdi2", clzdi2(0), 64) // 0 has 64 leading zeros
|
||||
|
||||
// Test ctzsi2 - count trailing zeros in 32-bit integer
|
||||
assertEqualInt32("ctzsi2", ctzsi2(1<<5), 5) // 0x00000020 has 5 trailing zeros
|
||||
assertEqualInt32("ctzsi2", ctzsi2(0x80000000), 31) // 0x80000000 has 31 trailing zeros
|
||||
assertEqualInt32("ctzsi2", ctzsi2(0), 32) // 0 has 32 trailing zeros
|
||||
|
||||
// Test ctzdi2 - count trailing zeros in 64-bit integer
|
||||
assertEqualInt32("ctzdi2", ctzdi2(1<<10), 10) // 0x0000000000000400 has 10 trailing zeros
|
||||
assertEqualInt32("ctzdi2", ctzdi2(0x8000000000000000), 63) // 0x8000000000000000 has 63 trailing zeros
|
||||
assertEqualInt32("ctzdi2", ctzdi2(0), 64) // 0 has 64 trailing zeros
|
||||
|
||||
// Test popcountsi2 - population count of 32-bit integer
|
||||
assertEqualInt32("popcountsi2", popcountsi2(0xF0F0F0F0), 16) // 0xF0F0F0F0 has 16 ones
|
||||
assertEqualInt32("popcountsi2", popcountsi2(0), 0) // 0 has 0 ones
|
||||
assertEqualInt32("popcountsi2", popcountsi2(0xFFFFFFFF), 32) // 0xFFFFFFFF has 32 ones
|
||||
|
||||
// Test popcountdi2 - population count of 64-bit integer
|
||||
assertEqualInt32("popcountdi2", popcountdi2(0xFFFF0000FFFF0000), 32) // 0xFFFF0000FFFF0000 has 32 ones
|
||||
assertEqualInt32("popcountdi2", popcountdi2(0), 0) // 0 has 0 ones
|
||||
assertEqualInt32("popcountdi2", popcountdi2(0xFFFFFFFFFFFFFFFF), 64) // 0xFFFFFFFFFFFFFFFF has 64 ones
|
||||
}
|
||||
|
||||
func testDivisionFunctions() {
|
||||
println("Testing division functions...")
|
||||
|
||||
// Test udivdi3 - unsigned 64-bit division
|
||||
assertEqualUint64("udivdi3", udivdi3(100, 5), 20)
|
||||
assertEqualUint64("udivdi3", udivdi3(18446744073709551615, 3), 6148914691236517205)
|
||||
assertEqualUint64("udivdi3", udivdi3(0, 123456789), 0)
|
||||
|
||||
// Test divdi3 - signed 64-bit division
|
||||
assertEqualInt64("divdi3", divdi3(20, 3), 6)
|
||||
assertEqualInt64("divdi3", divdi3(-20, 3), -6)
|
||||
assertEqualInt64("divdi3", divdi3(20, -3), -6)
|
||||
|
||||
// Test divdf3 - double precision division
|
||||
assertEqualFloat64("divdf3", divdf3(20.0, 3.0), 6.666666666666667, 1e-10)
|
||||
assertEqualFloat64("divdf3", divdf3(-20.0, 3.0), -6.666666666666667, 1e-10)
|
||||
|
||||
// Test divsf3 - single precision division
|
||||
assertEqualFloat32("divsf3", divsf3(20.0, 3.0), 6.6666665, 1e-6)
|
||||
assertEqualFloat32("divsf3", divsf3(-20.0, 3.0), -6.6666665, 1e-6)
|
||||
}
|
||||
|
||||
func testMultiplicationFunctions() {
|
||||
println("Testing multiplication functions...")
|
||||
|
||||
// Test muldi3 - signed 64-bit multiplication
|
||||
assertEqualInt64("muldi3", muldi3(5, 4), 20)
|
||||
assertEqualInt64("muldi3", muldi3(-5, 4), -20)
|
||||
assertEqualInt64("muldi3", muldi3(5, -4), -20)
|
||||
|
||||
// Test muldf3 - double precision multiplication
|
||||
assertEqualFloat64("muldf3", muldf3(3.0, 4.0), 12.0, 1e-10)
|
||||
assertEqualFloat64("muldf3", muldf3(-3.0, 4.0), -12.0, 1e-10)
|
||||
|
||||
// Test mulsf3 - single precision multiplication
|
||||
assertEqualFloat32("mulsf3", mulsf3(3.0, 4.0), 12.0, 1e-6)
|
||||
assertEqualFloat32("mulsf3", mulsf3(-3.0, 4.0), -12.0, 1e-6)
|
||||
}
|
||||
|
||||
func testSubtractionFunctions() {
|
||||
println("Testing subtraction functions...")
|
||||
|
||||
// Test subdf3 - double precision subtraction
|
||||
assertEqualFloat64("subdf3", subdf3(5.0, 3.0), 2.0, 1e-10)
|
||||
assertEqualFloat64("subdf3", subdf3(3.0, 5.0), -2.0, 1e-10)
|
||||
|
||||
// Test subsf3 - single precision subtraction
|
||||
assertEqualFloat32("subsf3", subsf3(5.0, 3.0), 2.0, 1e-6)
|
||||
assertEqualFloat32("subsf3", subsf3(3.0, 5.0), -2.0, 1e-6)
|
||||
}
|
||||
|
||||
func testConversionFunctions() {
|
||||
println("Testing conversion functions...")
|
||||
|
||||
// Test extendsfdf2 - single to double precision conversion
|
||||
// FIXME
|
||||
// assertEqualFloat64("extendsfdf2", extendsfdf2(3.14), 3.14, 1e-10)
|
||||
|
||||
// Test fixdfsi - double precision to int32 conversion
|
||||
assertEqualInt32("fixdfsi", fixdfsi(123.45), 123)
|
||||
assertEqualInt32("fixdfsi", fixdfsi(-123.45), -123)
|
||||
|
||||
// Test fixsfsi - single precision to int32 conversion
|
||||
assertEqualInt32("fixsfsi", fixsfsi(123.45), 123)
|
||||
assertEqualInt32("fixsfsi", fixsfsi(-123.45), -123)
|
||||
|
||||
// Test fixdfdi - double precision to int64 conversion
|
||||
assertEqualInt64("fixdfdi", fixdfdi(123456789.123), 123456789)
|
||||
assertEqualInt64("fixdfdi", fixdfdi(-123456789.123), -123456789)
|
||||
|
||||
// Test fixsfdi - single precision to int64 conversion
|
||||
// FIXME
|
||||
// assertEqualInt64("fixsfdi", fixsfdi(123456789.123), 123456789)
|
||||
// assertEqualInt64("fixsfdi", fixsfdi(-123456789.123), -123456789)
|
||||
|
||||
// Test floatsidf - int32 to double precision conversion
|
||||
assertEqualFloat64("floatsidf", floatsidf(42), 42.0, 1e-10)
|
||||
assertEqualFloat64("floatsidf", floatsidf(-100), -100.0, 1e-10)
|
||||
|
||||
// Test floatdidf - int64 to double precision conversion
|
||||
assertEqualFloat64("floatdidf", floatdidf(123456789), 123456789.0, 1e-10)
|
||||
assertEqualFloat64("floatdidf", floatdidf(-123456789), -123456789.0, 1e-10)
|
||||
}
|
||||
|
||||
func testShiftFunctions() {
|
||||
println("Testing shift functions...")
|
||||
|
||||
// Test ashldi3 - arithmetic shift left
|
||||
assertEqualInt64("ashldi3", ashldi3(1, 10), 1024)
|
||||
|
||||
// Test ashrdi3 - arithmetic shift right
|
||||
assertEqualInt64("ashrdi3", ashrdi3(1024, 10), 1)
|
||||
|
||||
// Test lshrdi3 - logical shift right
|
||||
assertEqualUint64("lshrdi3", lshrdi3(1024, 10), 1)
|
||||
assertEqualUint64("lshrdi3", lshrdi3(0x8000000000000000, 63), 1)
|
||||
}
|
||||
|
||||
func testBitManipulationFunctions() {
|
||||
println("Testing bit manipulation functions...")
|
||||
|
||||
// Test bswapsi2 - byte swap 32-bit integer
|
||||
assertEqualUint32("bswapsi2", bswapsi2(0x12345678), 0x78563412)
|
||||
|
||||
// Test bswapdi2 - byte swap 64-bit integer
|
||||
assertEqualUint64("bswapdi2", bswapdi2(0x1234567890ABCDEF), 0xEFCDAB9078563412)
|
||||
}
|
||||
|
||||
func main() {
|
||||
watchdog.Disable()
|
||||
println("Testing Compiler-RT Builtins Functions")
|
||||
println("=====================================")
|
||||
testAbsFunctions()
|
||||
testAddFunctions()
|
||||
testCountFunctions()
|
||||
testDivisionFunctions()
|
||||
testMultiplicationFunctions()
|
||||
testSubtractionFunctions()
|
||||
testConversionFunctions()
|
||||
testShiftFunctions()
|
||||
testBitManipulationFunctions()
|
||||
|
||||
println("\n=====================================")
|
||||
println("Test Results: %d total, %d passed, %d failed\n", totalTests, passedTests, failedTests)
|
||||
println("=====================================")
|
||||
|
||||
if failedTests == 0 {
|
||||
println("All tests PASSED!")
|
||||
} else {
|
||||
println("Some tests FAILED!")
|
||||
}
|
||||
}
|
||||
16
_demo/embed/esp32/watchdog/watchdog.go
Normal file
16
_demo/embed/esp32/watchdog/watchdog.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package watchdog
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
_ "unsafe"
|
||||
)
|
||||
|
||||
//go:linkname StoreUint32 llgo.atomicStore
|
||||
func StoreUint32(addr *uint32, val uint32)
|
||||
|
||||
func Disable() {
|
||||
StoreUint32((*uint32)(unsafe.Pointer(uintptr(0x3ff480A4))), 0x50D83AA1)
|
||||
|
||||
StoreUint32((*uint32)(unsafe.Pointer(uintptr(0x3ff4808C))), 0)
|
||||
StoreUint32((*uint32)(unsafe.Pointer(uintptr(0x3ff5f048))), 0)
|
||||
}
|
||||
31
_demo/embed/esp32/write/main.go
Normal file
31
_demo/embed/esp32/write/main.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/lib/c"
|
||||
)
|
||||
|
||||
//go:linkname write C.write
|
||||
func write(c.Int, *c.Char, c.SizeT) int
|
||||
|
||||
func main() {
|
||||
buf := c.Malloc(6)
|
||||
c.Memset(buf, 0, 6)
|
||||
c.Strncpy((*c.Char)(buf), c.Str("abcde"), 5)
|
||||
|
||||
if c.Strcmp((*c.Char)(buf), c.Str("abcde")) == 0 {
|
||||
write(1, c.Str("pass strcmp"), 11)
|
||||
}
|
||||
|
||||
if byte(c.Index((*c.Char)(buf), 0)) == 'a' {
|
||||
write(1, c.Str("pass index"), 10)
|
||||
}
|
||||
|
||||
c.Memset(buf, c.Int('A'), 5)
|
||||
if c.Strcmp((*c.Char)(buf), c.Str("AAAAA")) == 0 {
|
||||
write(1, c.Str("pass memeset"), 11)
|
||||
}
|
||||
|
||||
write(1, (*c.Char)(buf), 5)
|
||||
}
|
||||
5
_demo/embed/go.mod
Normal file
5
_demo/embed/go.mod
Normal file
@@ -0,0 +1,5 @@
|
||||
module github.com/goplus/llgo/_demo/embed
|
||||
|
||||
go 1.20
|
||||
|
||||
require github.com/goplus/lib v0.3.0
|
||||
2
_demo/embed/go.sum
Normal file
2
_demo/embed/go.sum
Normal file
@@ -0,0 +1,2 @@
|
||||
github.com/goplus/lib v0.3.0 h1:y0ZGb5Q/RikW1oMMB4Di7XIZIpuzh/7mlrR8HNbxXCA=
|
||||
github.com/goplus/lib v0.3.0/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0=
|
||||
21
_demo/embed/targetsbuild/C/c.go
Normal file
21
_demo/embed/targetsbuild/C/c.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package C
|
||||
|
||||
func XhandleHardFault() {
|
||||
|
||||
}
|
||||
|
||||
func Reset_Handler() {
|
||||
|
||||
}
|
||||
|
||||
func XhandleInterrupt() {
|
||||
|
||||
}
|
||||
|
||||
type dyn64 struct {
|
||||
// Fields for dynamic loader
|
||||
}
|
||||
|
||||
// For nintendo switch
|
||||
func X__dynamic_loader(base uintptr, dyn *dyn64) {
|
||||
}
|
||||
180
_demo/embed/targetsbuild/build.sh
Normal file
180
_demo/embed/targetsbuild/build.sh
Normal file
@@ -0,0 +1,180 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Function to display usage information
|
||||
show_usage() {
|
||||
cat << EOF
|
||||
Usage: $(basename "$0") [OPTIONS] [TARGET_FILE]
|
||||
|
||||
Build targets for llgo across multiple platforms.
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Show this help message and exit
|
||||
|
||||
ARGUMENTS:
|
||||
TARGET_FILE Optional. A text file containing target names, one per line.
|
||||
Lines starting with # are treated as comments and ignored.
|
||||
Empty lines are also ignored.
|
||||
|
||||
BEHAVIOR:
|
||||
Without TARGET_FILE:
|
||||
- Automatically discovers all targets from ../../targets/*.json files
|
||||
- Extracts target names from JSON filenames
|
||||
|
||||
With TARGET_FILE:
|
||||
- Reads target names from the specified file
|
||||
- Supports comments (lines starting with #)
|
||||
- Ignores empty lines and whitespace
|
||||
|
||||
IGNORED TARGETS:
|
||||
The following targets are automatically ignored and not built:
|
||||
atmega1280, atmega2560, atmega328p, atmega32u4, attiny85,
|
||||
fe310, k210, riscv32, riscv64, rp2040
|
||||
|
||||
RESULT CATEGORIES:
|
||||
✅ Successful: Build completed successfully
|
||||
🔕 Ignored: Target is in the ignore list
|
||||
⚠️ Warned: Build failed with configuration warnings
|
||||
❌ Failed: Build failed with errors
|
||||
|
||||
EXIT CODES:
|
||||
0 All builds successful, ignored, or warned only
|
||||
1 One or more builds failed with errors
|
||||
|
||||
EXAMPLES:
|
||||
$(basename "$0") # Build all targets from JSON files
|
||||
$(basename "$0") my-targets.txt # Build targets from file
|
||||
$(basename "$0") --help # Show this help
|
||||
|
||||
TARGET FILE FORMAT:
|
||||
# This is a comment
|
||||
esp32
|
||||
cortex-m4
|
||||
|
||||
# Another comment
|
||||
riscv64
|
||||
EOF
|
||||
}
|
||||
|
||||
# Check for help flag
|
||||
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
|
||||
show_usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check for invalid number of arguments
|
||||
if [ $# -gt 1 ]; then
|
||||
echo "Error: Too many arguments."
|
||||
echo "Use '$(basename "$0") --help' for usage information."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Initialize arrays to store results
|
||||
successful_targets=()
|
||||
ignored_targets=()
|
||||
warned_targets=()
|
||||
failed_targets=()
|
||||
targets_to_build=()
|
||||
|
||||
# Define ignore list
|
||||
ignore_list=(
|
||||
"atmega1280"
|
||||
"atmega2560"
|
||||
"atmega328p"
|
||||
"atmega32u4"
|
||||
"attiny85"
|
||||
"fe310"
|
||||
"k210"
|
||||
"riscv32"
|
||||
"riscv64"
|
||||
"rp2040"
|
||||
)
|
||||
|
||||
# Build the targets list based on input method
|
||||
if [ $# -eq 1 ]; then
|
||||
# Read targets from file
|
||||
target_file="$1"
|
||||
if [ ! -f "$target_file" ]; then
|
||||
echo "Error: Target file '$target_file' not found."
|
||||
echo "Use '$(basename "$0") --help' for usage information."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while IFS= read -r target || [[ -n "$target" ]]; do
|
||||
# Skip empty lines and comments
|
||||
if [[ -z "$target" || "$target" =~ ^[[:space:]]*# ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Trim whitespace
|
||||
target=$(echo "$target" | xargs)
|
||||
targets_to_build+=("$target")
|
||||
done < "$target_file"
|
||||
else
|
||||
# Use targets from *.json files
|
||||
for target_file in ../../../targets/*.json; do
|
||||
# Extract target name from filename (remove path and .json extension)
|
||||
target=$(basename "$target_file" .json)
|
||||
targets_to_build+=("$target")
|
||||
done
|
||||
fi
|
||||
|
||||
# Process each target
|
||||
for target in "${targets_to_build[@]}"; do
|
||||
# Check if target is in ignore list
|
||||
if [[ " ${ignore_list[@]} " =~ " ${target} " ]]; then
|
||||
echo 🔕 $target "(ignored)"
|
||||
ignored_targets+=("$target")
|
||||
continue
|
||||
fi
|
||||
|
||||
output=$(../../../llgo.sh build -target $target -o hello.elf . 2>&1)
|
||||
if [ $? -eq 0 ]; then
|
||||
echo ✅ $target `file hello.elf`
|
||||
successful_targets+=("$target")
|
||||
else
|
||||
# Check if output contains warning messages
|
||||
if echo "$output" | grep -q "does not have a valid LLVM target triple\|does not have a valid CPU configuration"; then
|
||||
echo ⚠️ $target
|
||||
echo "$output"
|
||||
warned_targets+=("$target")
|
||||
else
|
||||
echo ❌ $target
|
||||
echo "$output"
|
||||
failed_targets+=("$target")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "----------------------------------------"
|
||||
|
||||
# Output successful targets
|
||||
echo "Successful targets (${#successful_targets[@]} total):"
|
||||
for target in "${successful_targets[@]}"; do
|
||||
echo "$target"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Ignored targets (${#ignored_targets[@]} total):"
|
||||
for target in "${ignored_targets[@]}"; do
|
||||
echo "$target"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Warned targets (${#warned_targets[@]} total):"
|
||||
for target in "${warned_targets[@]}"; do
|
||||
echo "$target"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Failed targets (${#failed_targets[@]} total):"
|
||||
for target in "${failed_targets[@]}"; do
|
||||
echo "$target"
|
||||
done
|
||||
|
||||
# Exit with error code if there are any failed targets
|
||||
if [ ${#failed_targets[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
echo "Build failed with ${#failed_targets[@]} failed targets."
|
||||
exit 1
|
||||
fi
|
||||
6
_demo/embed/targetsbuild/empty.go
Normal file
6
_demo/embed/targetsbuild/empty.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package main
|
||||
|
||||
import _ "github.com/goplus/llgo/_demo/embed/targetsbuild/C"
|
||||
|
||||
func main() {
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
module github.com/goplus/llgo/_demo
|
||||
|
||||
go 1.20
|
||||
|
||||
require github.com/goplus/lib v0.2.0
|
||||
@@ -3,8 +3,8 @@ package main
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/goplus/llgo/_demo/async/async"
|
||||
"github.com/goplus/llgo/_demo/async/timeout"
|
||||
"github.com/goplus/llgo/_demo/go/async/async"
|
||||
"github.com/goplus/llgo/_demo/go/async/timeout"
|
||||
)
|
||||
|
||||
func Sleep(i int, d time.Duration) async.Future[int] {
|
||||
@@ -3,7 +3,7 @@ package timeout
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/goplus/llgo/_demo/async/async"
|
||||
"github.com/goplus/llgo/_demo/go/async/async"
|
||||
)
|
||||
|
||||
func Timeout(d time.Duration) async.Future[async.Void] {
|
||||
@@ -3,11 +3,13 @@ package main
|
||||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var data bytes.Buffer
|
||||
cmd := exec.Command("echo", "hello llgo")
|
||||
cmd.Dir = filepath.Dir("./")
|
||||
cmd.Stdout = &data
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
1
_demo/go/export/.gitignore
vendored
Normal file
1
_demo/go/export/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
libexport.h
|
||||
29
_demo/go/export/c/c.go
Normal file
29
_demo/go/export/c/c.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package C
|
||||
|
||||
// XType - struct for export.go to use
|
||||
type XType struct {
|
||||
ID int32 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Value float64 `json:"value"`
|
||||
Flag bool `json:"flag"`
|
||||
}
|
||||
|
||||
func XAdd(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
|
||||
func Sub(a, b int64) int64 {
|
||||
return a - b
|
||||
}
|
||||
|
||||
func sub(a, b uint32) uint32 {
|
||||
return a - b
|
||||
}
|
||||
|
||||
func Xmul(a, b float32) float32 {
|
||||
return a * b
|
||||
}
|
||||
|
||||
func Concat(a, b string) string {
|
||||
return a + b
|
||||
}
|
||||
674
_demo/go/export/export.go
Normal file
674
_demo/go/export/export.go
Normal file
@@ -0,0 +1,674 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
C "github.com/goplus/llgo/_demo/go/export/c"
|
||||
)
|
||||
|
||||
// assert helper function for testing
|
||||
func assert[T comparable](got, expected T, message string) {
|
||||
if got != expected {
|
||||
println("ASSERTION FAILED:", message)
|
||||
println(" Expected:", expected)
|
||||
println(" Got: ", got)
|
||||
panic("assertion failed: " + message)
|
||||
}
|
||||
println("✓", message)
|
||||
}
|
||||
|
||||
// Small struct
|
||||
type SmallStruct struct {
|
||||
ID int8 `json:"id"`
|
||||
Flag bool `json:"flag"`
|
||||
}
|
||||
|
||||
// Large struct
|
||||
type LargeStruct struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Values [10]float64 `json:"values"`
|
||||
Metadata map[string]int `json:"metadata"`
|
||||
Children []SmallStruct `json:"children"`
|
||||
Extra1 int32 `json:"extra1"`
|
||||
Extra2 uint64 `json:"extra2"`
|
||||
Extra3 float32 `json:"extra3"`
|
||||
Extra4 bool `json:"extra4"`
|
||||
Extra5 uintptr `json:"extra5"`
|
||||
}
|
||||
|
||||
// Self-referential struct
|
||||
type Node struct {
|
||||
Data int `json:"data"`
|
||||
Next *Node `json:"next"`
|
||||
}
|
||||
|
||||
// Named types
|
||||
type MyInt int
|
||||
type MyString string
|
||||
|
||||
// Function types for callbacks
|
||||
//
|
||||
//llgo:type C
|
||||
type IntCallback func(int) int
|
||||
|
||||
//llgo:type C
|
||||
type StringCallback func(string) string
|
||||
|
||||
//llgo:type C
|
||||
type VoidCallback func()
|
||||
|
||||
// Complex struct with mixed arrays and slices
|
||||
type ComplexData struct {
|
||||
Matrix [3][4]int32 `json:"matrix"` // 2D array
|
||||
Slices [][]string `json:"slices"` // slice of slices - commented out
|
||||
IntArray [5]int `json:"int_array"` // 1D array
|
||||
DataList []float64 `json:"data_list"` // slice - commented out
|
||||
}
|
||||
|
||||
//export HelloWorld
|
||||
func HelloWorld() {
|
||||
println("Hello, World!")
|
||||
}
|
||||
|
||||
// Functions with small struct parameters and return values
|
||||
|
||||
//export CreateSmallStruct
|
||||
func CreateSmallStruct(id int8, flag bool) SmallStruct {
|
||||
return SmallStruct{ID: id, Flag: flag}
|
||||
}
|
||||
|
||||
//export ProcessSmallStruct
|
||||
func ProcessSmallStruct(s SmallStruct) SmallStruct {
|
||||
s.ID += 1
|
||||
s.Flag = !s.Flag
|
||||
return s
|
||||
}
|
||||
|
||||
//export ProcessSmallStructPtr
|
||||
func ProcessSmallStructPtr(s *SmallStruct) *SmallStruct {
|
||||
if s != nil {
|
||||
s.ID *= 2
|
||||
s.Flag = !s.Flag
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Functions with large struct parameters and return values
|
||||
|
||||
//export CreateLargeStruct
|
||||
func CreateLargeStruct(id int64, name string) LargeStruct {
|
||||
return LargeStruct{
|
||||
ID: id,
|
||||
Name: name,
|
||||
Values: [10]float64{1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.0},
|
||||
Metadata: map[string]int{"count": 42, "size": 100},
|
||||
Children: []SmallStruct{{ID: 1, Flag: true}, {ID: 2, Flag: false}},
|
||||
Extra1: 12345,
|
||||
Extra2: 67890,
|
||||
Extra3: 3.14,
|
||||
Extra4: true,
|
||||
Extra5: 0x1000,
|
||||
}
|
||||
}
|
||||
|
||||
//export ProcessLargeStruct
|
||||
func ProcessLargeStruct(ls LargeStruct) int64 {
|
||||
total := ls.ID + int64(len(ls.Name))
|
||||
for _, v := range ls.Values {
|
||||
total += int64(v)
|
||||
}
|
||||
total += int64(len(ls.Children))
|
||||
total += int64(ls.Extra1) + int64(ls.Extra2) + int64(ls.Extra3)
|
||||
if ls.Extra4 {
|
||||
total += 1000
|
||||
}
|
||||
total += int64(ls.Extra5)
|
||||
return total
|
||||
}
|
||||
|
||||
//export ProcessLargeStructPtr
|
||||
func ProcessLargeStructPtr(ls *LargeStruct) *LargeStruct {
|
||||
if ls != nil {
|
||||
ls.ID += 100
|
||||
ls.Name = "processed_" + ls.Name
|
||||
ls.Extra1 *= 2
|
||||
ls.Extra4 = !ls.Extra4
|
||||
}
|
||||
return ls
|
||||
}
|
||||
|
||||
// Functions with self-referential struct
|
||||
|
||||
//export CreateNode
|
||||
func CreateNode(data int) *Node {
|
||||
return &Node{Data: data, Next: nil}
|
||||
}
|
||||
|
||||
//export LinkNodes
|
||||
func LinkNodes(first, second *Node) int {
|
||||
if first != nil && second != nil {
|
||||
first.Next = second
|
||||
return first.Data + second.Data // Return sum for verification
|
||||
}
|
||||
if first != nil {
|
||||
return first.Data + 1000 // Return data + offset if only first exists
|
||||
}
|
||||
return 2000 // Return fixed value if both are nil
|
||||
}
|
||||
|
||||
//export TraverseNodes
|
||||
func TraverseNodes(head *Node) int {
|
||||
count := 0
|
||||
current := head
|
||||
for current != nil {
|
||||
count++
|
||||
current = current.Next
|
||||
if count > 100 { // Safety check
|
||||
break
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// Functions covering all basic types
|
||||
|
||||
//export ProcessBool
|
||||
func ProcessBool(b bool) bool {
|
||||
return !b
|
||||
}
|
||||
|
||||
//export ProcessInt8
|
||||
func ProcessInt8(x int8) int8 {
|
||||
return x + 1
|
||||
}
|
||||
|
||||
//export ProcessUint8
|
||||
func ProcessUint8(x uint8) uint8 {
|
||||
return x + 1
|
||||
}
|
||||
|
||||
//export ProcessInt16
|
||||
func ProcessInt16(x int16) int16 {
|
||||
return x * 2
|
||||
}
|
||||
|
||||
//export ProcessUint16
|
||||
func ProcessUint16(x uint16) uint16 {
|
||||
return x * 2
|
||||
}
|
||||
|
||||
//export ProcessInt32
|
||||
func ProcessInt32(x int32) int32 {
|
||||
return x * 3
|
||||
}
|
||||
|
||||
//export ProcessUint32
|
||||
func ProcessUint32(x uint32) uint32 {
|
||||
return x * 3
|
||||
}
|
||||
|
||||
//export ProcessInt64
|
||||
func ProcessInt64(x int64) int64 {
|
||||
return x * 4
|
||||
}
|
||||
|
||||
//export ProcessUint64
|
||||
func ProcessUint64(x uint64) uint64 {
|
||||
return x * 4
|
||||
}
|
||||
|
||||
//export ProcessInt
|
||||
func ProcessInt(x int) int {
|
||||
return x * 11
|
||||
}
|
||||
|
||||
//export ProcessUint
|
||||
func ProcessUint(x uint) uint {
|
||||
return x * 21
|
||||
}
|
||||
|
||||
//export ProcessUintptr
|
||||
func ProcessUintptr(x uintptr) uintptr {
|
||||
return x + 300
|
||||
}
|
||||
|
||||
//export ProcessFloat32
|
||||
func ProcessFloat32(x float32) float32 {
|
||||
return x * 1.5
|
||||
}
|
||||
|
||||
//export ProcessFloat64
|
||||
func ProcessFloat64(x float64) float64 {
|
||||
return x * 2.5
|
||||
}
|
||||
|
||||
//export ProcessString
|
||||
func ProcessString(s string) string {
|
||||
return "processed_" + s
|
||||
}
|
||||
|
||||
//export ProcessUnsafePointer
|
||||
func ProcessUnsafePointer(p unsafe.Pointer) unsafe.Pointer {
|
||||
return p
|
||||
}
|
||||
|
||||
// Functions with named types
|
||||
|
||||
//export ProcessMyInt
|
||||
func ProcessMyInt(x MyInt) MyInt {
|
||||
return x * 10
|
||||
}
|
||||
|
||||
//export ProcessMyString
|
||||
func ProcessMyString(s MyString) MyString {
|
||||
return MyString("modified_" + string(s))
|
||||
}
|
||||
|
||||
// Functions with arrays, slices, maps, channels
|
||||
|
||||
//export ProcessIntArray
|
||||
func ProcessIntArray(arr [5]int) int {
|
||||
total := 0
|
||||
for _, v := range arr {
|
||||
total += v
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
//export CreateComplexData
|
||||
func CreateComplexData() ComplexData {
|
||||
return ComplexData{
|
||||
Matrix: [3][4]int32{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}},
|
||||
Slices: [][]string{{"helo"}},
|
||||
IntArray: [5]int{10, 20, 30, 40, 50},
|
||||
DataList: []float64{1.0},
|
||||
}
|
||||
}
|
||||
|
||||
//export ProcessComplexData
|
||||
func ProcessComplexData(data ComplexData) int32 {
|
||||
// Sum all matrix elements
|
||||
var sum int32
|
||||
for i := 0; i < 3; i++ {
|
||||
for j := 0; j < 4; j++ {
|
||||
sum += data.Matrix[i][j]
|
||||
}
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
// Functions with multidimensional arrays as parameters and return values
|
||||
|
||||
//export ProcessMatrix2D
|
||||
func ProcessMatrix2D(matrix [3][4]int32) int32 {
|
||||
var sum int32
|
||||
for i := 0; i < 3; i++ {
|
||||
for j := 0; j < 4; j++ {
|
||||
sum += matrix[i][j]
|
||||
}
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
//export CreateMatrix1D
|
||||
func CreateMatrix1D() [4]int32 {
|
||||
return [4]int32{1, 2, 3, 4}
|
||||
}
|
||||
|
||||
//export CreateMatrix2D
|
||||
func CreateMatrix2D() [3][4]int32 {
|
||||
return [3][4]int32{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}
|
||||
}
|
||||
|
||||
//export ProcessMatrix3D
|
||||
func ProcessMatrix3D(cube [2][3][4]uint8) uint32 {
|
||||
var sum uint32
|
||||
for i := 0; i < 2; i++ {
|
||||
for j := 0; j < 3; j++ {
|
||||
for k := 0; k < 4; k++ {
|
||||
sum += uint32(cube[i][j][k])
|
||||
}
|
||||
}
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
//export CreateMatrix3D
|
||||
func CreateMatrix3D() [2][3][4]uint8 {
|
||||
var cube [2][3][4]uint8
|
||||
val := uint8(1)
|
||||
for i := 0; i < 2; i++ {
|
||||
for j := 0; j < 3; j++ {
|
||||
for k := 0; k < 4; k++ {
|
||||
cube[i][j][k] = val
|
||||
val++
|
||||
}
|
||||
}
|
||||
}
|
||||
return cube
|
||||
}
|
||||
|
||||
//export ProcessGrid5x4
|
||||
func ProcessGrid5x4(grid [5][4]float64) float64 {
|
||||
var sum float64
|
||||
for i := 0; i < 5; i++ {
|
||||
for j := 0; j < 4; j++ {
|
||||
sum += grid[i][j]
|
||||
}
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
//export CreateGrid5x4
|
||||
func CreateGrid5x4() [5][4]float64 {
|
||||
var grid [5][4]float64
|
||||
val := 1.0
|
||||
for i := 0; i < 5; i++ {
|
||||
for j := 0; j < 4; j++ {
|
||||
grid[i][j] = val
|
||||
val += 0.5
|
||||
}
|
||||
}
|
||||
return grid
|
||||
}
|
||||
|
||||
//export ProcessIntSlice
|
||||
func ProcessIntSlice(slice []int) int {
|
||||
total := 0
|
||||
for _, v := range slice {
|
||||
total += v
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
//export ProcessStringMap
|
||||
func ProcessStringMap(m map[string]int) int {
|
||||
total := 0
|
||||
for _, v := range m {
|
||||
total += v
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
//export ProcessIntChannel
|
||||
func ProcessIntChannel(ch chan int) int {
|
||||
select {
|
||||
case val := <-ch:
|
||||
return val
|
||||
default:
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
// Functions with function callbacks
|
||||
|
||||
//export ProcessWithIntCallback
|
||||
func ProcessWithIntCallback(x int, callback IntCallback) int {
|
||||
if callback != nil {
|
||||
return callback(x)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
//export ProcessWithStringCallback
|
||||
func ProcessWithStringCallback(s string, callback StringCallback) string {
|
||||
if callback != nil {
|
||||
return callback(s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
//export ProcessWithVoidCallback
|
||||
func ProcessWithVoidCallback(callback VoidCallback) int {
|
||||
if callback != nil {
|
||||
callback()
|
||||
return 123 // Return non-zero to indicate callback was called
|
||||
}
|
||||
return 456 // Return different value if callback is nil
|
||||
}
|
||||
|
||||
//export ProcessThreeUnnamedParams
|
||||
func ProcessThreeUnnamedParams(a int, s string, b bool) float64 {
|
||||
result := float64(a) + float64(len(s))
|
||||
if b {
|
||||
result *= 1.5
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Functions with interface
|
||||
|
||||
//export ProcessInterface
|
||||
func ProcessInterface(i interface{}) int {
|
||||
switch v := i.(type) {
|
||||
case int:
|
||||
return v + 100
|
||||
case string:
|
||||
return len(v) * 10
|
||||
default:
|
||||
return 999 // Non-zero default to avoid false positives
|
||||
}
|
||||
}
|
||||
|
||||
// Functions with various parameter counts
|
||||
|
||||
//export NoParams
|
||||
func NoParams() int {
|
||||
return 42
|
||||
}
|
||||
|
||||
//export OneParam
|
||||
func OneParam(x int) int {
|
||||
return x * 2
|
||||
}
|
||||
|
||||
//export TwoParams
|
||||
func TwoParams(a int, b string) string {
|
||||
return string(rune(a)) + b
|
||||
}
|
||||
|
||||
//export ThreeParams
|
||||
func ThreeParams(a int32, b float64, c bool) float64 {
|
||||
result := float64(a) + b
|
||||
if c {
|
||||
result *= 2
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
//export MultipleParams
|
||||
func MultipleParams(a int8, b uint16, c int32, d uint64, e float32, f float64, g string, h bool) string {
|
||||
result := g + "_" + string(rune('A'+a)) + string(rune('0'+b%10)) + string(rune('0'+c%10))
|
||||
if h {
|
||||
result += "_true"
|
||||
}
|
||||
return result + "_" + string(rune('0'+int(d%10))) + "_" + string(rune('0'+int(e)%10)) + "_" + string(rune('0'+int(f)%10))
|
||||
}
|
||||
|
||||
//export NoParamNames
|
||||
func NoParamNames(int8, int16, bool) int32 {
|
||||
return 789 // Return non-zero value for testing, params are unnamed by design
|
||||
}
|
||||
|
||||
// Functions returning no value
|
||||
|
||||
//export NoReturn
|
||||
func NoReturn(message string) {
|
||||
println("Message:", message)
|
||||
}
|
||||
|
||||
// Functions using XType from c package
|
||||
|
||||
//export CreateXType
|
||||
func CreateXType(id int32, name string, value float64, flag bool) C.XType {
|
||||
return C.XType{
|
||||
ID: id,
|
||||
Name: name,
|
||||
Value: value,
|
||||
Flag: flag,
|
||||
}
|
||||
}
|
||||
|
||||
//export ProcessXType
|
||||
func ProcessXType(x C.XType) C.XType {
|
||||
x.ID += 100
|
||||
x.Name = "processed_" + x.Name
|
||||
x.Value *= 2.0
|
||||
x.Flag = !x.Flag
|
||||
return x
|
||||
}
|
||||
|
||||
//export ProcessXTypePtr
|
||||
func ProcessXTypePtr(x *C.XType) *C.XType {
|
||||
if x != nil {
|
||||
x.ID *= 2
|
||||
x.Name = "ptr_" + x.Name
|
||||
x.Value += 10.0
|
||||
x.Flag = !x.Flag
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func main() {
|
||||
println("=== Export Demo ===")
|
||||
|
||||
// Test small struct
|
||||
small := CreateSmallStruct(5, true)
|
||||
assert(small.ID, int8(5), "CreateSmallStruct ID should be 5")
|
||||
assert(small.Flag, true, "CreateSmallStruct Flag should be true")
|
||||
println("Small struct:", small.ID, small.Flag)
|
||||
|
||||
processed := ProcessSmallStruct(small)
|
||||
assert(processed.ID, int8(6), "ProcessSmallStruct should increment ID to 6")
|
||||
assert(processed.Flag, false, "ProcessSmallStruct should flip Flag to false")
|
||||
println("Processed small:", processed.ID, processed.Flag)
|
||||
|
||||
// Test large struct
|
||||
large := CreateLargeStruct(12345, "test")
|
||||
assert(large.ID, int64(12345), "CreateLargeStruct ID should be 12345")
|
||||
assert(large.Name, "test", "CreateLargeStruct Name should be 'test'")
|
||||
println("Large struct ID:", large.ID, "Name:", large.Name)
|
||||
|
||||
total := ProcessLargeStruct(large)
|
||||
// Expected calculation:
|
||||
// ID: 12345, Name len: 4, Values: 1+2+3+4+5+6+7+8+9+10=55, Children len: 2
|
||||
// Extra1: 12345, Extra2: 67890, Extra3: 3, Extra4: +1000, Extra5: 4096
|
||||
expectedTotal := int64(12345 + 4 + 55 + 2 + 12345 + 67890 + 3 + 1000 + 4096)
|
||||
assert(total, expectedTotal, "ProcessLargeStruct total should match expected calculation")
|
||||
println("Large struct total:", total)
|
||||
|
||||
// Test self-referential struct
|
||||
node1 := CreateNode(100)
|
||||
node2 := CreateNode(200)
|
||||
linkResult := LinkNodes(node1, node2)
|
||||
assert(linkResult, 300, "LinkNodes should return sum of node data (100 + 200)")
|
||||
|
||||
count := TraverseNodes(node1)
|
||||
assert(count, 2, "TraverseNodes should count 2 linked nodes")
|
||||
println("Node count:", count)
|
||||
|
||||
// Test basic types with assertions
|
||||
assert(ProcessBool(true), false, "ProcessBool(true) should return false")
|
||||
assert(ProcessInt8(10), int8(11), "ProcessInt8(10) should return 11")
|
||||
f32Result := ProcessFloat32(3.14)
|
||||
// Float comparison with tolerance
|
||||
if f32Result < 4.7 || f32Result > 4.72 {
|
||||
println("ASSERTION FAILED: ProcessFloat32(3.14) should return ~4.71, got:", f32Result)
|
||||
panic("float assertion failed")
|
||||
}
|
||||
println("✓ ProcessFloat32(3.14) returns ~4.71")
|
||||
|
||||
assert(ProcessString("hello"), "processed_hello", "ProcessString should prepend 'processed_'")
|
||||
|
||||
println("Bool:", ProcessBool(true))
|
||||
println("Int8:", ProcessInt8(10))
|
||||
println("Float32:", ProcessFloat32(3.14))
|
||||
println("String:", ProcessString("hello"))
|
||||
|
||||
// Test named types
|
||||
myInt := ProcessMyInt(MyInt(42))
|
||||
assert(myInt, MyInt(420), "ProcessMyInt(42) should return 420")
|
||||
println("MyInt:", int(myInt))
|
||||
|
||||
myStr := ProcessMyString(MyString("world"))
|
||||
assert(myStr, MyString("modified_world"), "ProcessMyString should prepend 'modified_'")
|
||||
println("MyString:", string(myStr))
|
||||
|
||||
// Test collections
|
||||
arr := [5]int{1, 2, 3, 4, 5}
|
||||
arrSum := ProcessIntArray(arr)
|
||||
assert(arrSum, 15, "ProcessIntArray([1,2,3,4,5]) should return 15")
|
||||
println("Array sum:", arrSum)
|
||||
|
||||
slice := []int{10, 20, 30}
|
||||
sliceSum := ProcessIntSlice(slice)
|
||||
assert(sliceSum, 60, "ProcessIntSlice([10,20,30]) should return 60")
|
||||
println("Slice sum:", sliceSum)
|
||||
|
||||
m := make(map[string]int)
|
||||
m["a"] = 100
|
||||
m["b"] = 200
|
||||
mapSum := ProcessStringMap(m)
|
||||
assert(mapSum, 300, "ProcessStringMap({'a':100,'b':200}) should return 300")
|
||||
println("Map sum:", mapSum)
|
||||
|
||||
// Test multidimensional arrays
|
||||
matrix2d := CreateMatrix2D()
|
||||
matrix2dSum := ProcessMatrix2D(matrix2d)
|
||||
assert(matrix2dSum, int32(78), "ProcessMatrix2D should return 78 (sum of 1+2+...+12)")
|
||||
println("Matrix2D sum:", matrix2dSum)
|
||||
|
||||
matrix3d := CreateMatrix3D()
|
||||
matrix3dSum := ProcessMatrix3D(matrix3d)
|
||||
assert(matrix3dSum, uint32(300), "ProcessMatrix3D should return 300")
|
||||
println("Matrix3D sum:", matrix3dSum)
|
||||
|
||||
grid5x4 := CreateGrid5x4()
|
||||
gridSum := ProcessGrid5x4(grid5x4)
|
||||
assert(gridSum, 115.0, "ProcessGrid5x4 should return 115.0")
|
||||
println("Grid5x4 sum:", gridSum)
|
||||
|
||||
// Test complex data with multidimensional arrays
|
||||
complexData := CreateComplexData()
|
||||
complexSum := ProcessComplexData(complexData)
|
||||
assert(complexSum, int32(78), "ProcessComplexData should return 78")
|
||||
println("ComplexData matrix sum:", complexSum)
|
||||
|
||||
// Test various parameter counts
|
||||
assert(NoParams(), 42, "NoParams should return 42")
|
||||
assert(OneParam(5), 10, "OneParam(5) should return 10")
|
||||
assert(TwoParams(65, "_test"), "A_test", "TwoParams should return 'A_test'")
|
||||
assert(ThreeParams(10, 2.5, true), 25.0, "ThreeParams should return 25.0")
|
||||
assert(NoParamNames(1, 2, false), int32(789), "NoParamNames should return 789")
|
||||
|
||||
println("NoParams:", NoParams())
|
||||
println("OneParam:", OneParam(5))
|
||||
println("TwoParams:", TwoParams(65, "_test"))
|
||||
println("ThreeParams:", ThreeParams(10, 2.5, true))
|
||||
println("MultipleParams:", MultipleParams(1, 2, 3, 4, 5.0, 6.0, "result", true))
|
||||
println("NoParamNames:", NoParamNames(1, 2, false))
|
||||
|
||||
// Test XType from c package
|
||||
xtype := CreateXType(42, "test", 3.14, true)
|
||||
println("XType:", xtype.ID, xtype.Name, xtype.Value, xtype.Flag)
|
||||
|
||||
processedX := ProcessXType(xtype)
|
||||
println("Processed XType:", processedX.ID, processedX.Name, processedX.Value, processedX.Flag)
|
||||
|
||||
ptrX := ProcessXTypePtr(&xtype)
|
||||
if ptrX != nil {
|
||||
println("Ptr XType:", ptrX.ID, ptrX.Name, ptrX.Value, ptrX.Flag)
|
||||
}
|
||||
|
||||
// Test callback functions
|
||||
intResult := ProcessWithIntCallback(10, func(x int) int { return x * 3 })
|
||||
println("IntCallback result:", intResult)
|
||||
|
||||
stringResult := ProcessWithStringCallback("hello", func(s string) string { return s + "_callback" })
|
||||
println("StringCallback result:", stringResult)
|
||||
|
||||
ProcessWithVoidCallback(func() { println("VoidCallback executed") })
|
||||
|
||||
NoReturn("demo completed")
|
||||
}
|
||||
315
_demo/go/export/libexport.h.want
Normal file
315
_demo/go/export/libexport.h.want
Normal file
@@ -0,0 +1,315 @@
|
||||
/* Code generated by llgo; DO NOT EDIT. */
|
||||
|
||||
#ifndef __LIBEXPORT_H_
|
||||
#define __LIBEXPORT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Platform-specific symbol renaming macro
|
||||
#ifdef __APPLE__
|
||||
#define GO_SYMBOL_RENAME(go_name) __asm("_" go_name);
|
||||
#else
|
||||
#define GO_SYMBOL_RENAME(go_name) __asm(go_name);
|
||||
#endif
|
||||
|
||||
// Go runtime types
|
||||
typedef struct { const char *p; intptr_t n; } GoString;
|
||||
typedef struct { void *data; intptr_t len; intptr_t cap; } GoSlice;
|
||||
typedef struct { void *data; } GoMap;
|
||||
typedef struct { void *data; } GoChan;
|
||||
typedef struct { void *data; void *type; } GoInterface;
|
||||
typedef struct { float real; float imag; } GoComplex64;
|
||||
typedef struct { double real; double imag; } GoComplex128;
|
||||
|
||||
typedef struct {
|
||||
int32_t Matrix[3][4];
|
||||
GoSlice Slices;
|
||||
intptr_t IntArray[5];
|
||||
GoSlice DataList;
|
||||
} main_ComplexData;
|
||||
|
||||
typedef struct {
|
||||
double data[5][4];
|
||||
} Array_double_5_4;
|
||||
|
||||
typedef struct {
|
||||
int8_t ID;
|
||||
_Bool Flag;
|
||||
} main_SmallStruct;
|
||||
|
||||
typedef struct {
|
||||
int64_t ID;
|
||||
GoString Name;
|
||||
double Values[10];
|
||||
GoMap Metadata;
|
||||
GoSlice Children;
|
||||
int32_t Extra1;
|
||||
uint64_t Extra2;
|
||||
float Extra3;
|
||||
_Bool Extra4;
|
||||
uintptr_t Extra5;
|
||||
} main_LargeStruct;
|
||||
|
||||
typedef struct {
|
||||
int32_t data[4];
|
||||
} Array_int32_t_4;
|
||||
|
||||
typedef struct {
|
||||
int32_t data[3][4];
|
||||
} Array_int32_t_3_4;
|
||||
|
||||
typedef struct {
|
||||
uint8_t data[2][3][4];
|
||||
} Array_uint8_t_2_3_4;
|
||||
|
||||
typedef struct main_Node main_Node;
|
||||
struct main_Node {
|
||||
intptr_t Data;
|
||||
main_Node* Next;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int32_t ID;
|
||||
GoString Name;
|
||||
double Value;
|
||||
_Bool Flag;
|
||||
} C_XType;
|
||||
|
||||
typedef intptr_t main_MyInt;
|
||||
|
||||
typedef GoString main_MyString;
|
||||
|
||||
typedef intptr_t (*main_IntCallback)(intptr_t);
|
||||
|
||||
typedef GoString (*main_StringCallback)(GoString);
|
||||
|
||||
typedef void (*main_VoidCallback)(void);
|
||||
|
||||
GoString
|
||||
Concat(GoString a, GoString b);
|
||||
|
||||
int64_t
|
||||
Sub(int64_t a, int64_t b);
|
||||
|
||||
intptr_t
|
||||
Add(intptr_t a, intptr_t b);
|
||||
|
||||
float
|
||||
mul(float a, float b);
|
||||
|
||||
void
|
||||
github_com_goplus_llgo__demo_go_export_c_init(void) GO_SYMBOL_RENAME("github.com/goplus/llgo/_demo/go/export/c.init")
|
||||
|
||||
main_ComplexData
|
||||
CreateComplexData(void);
|
||||
|
||||
Array_double_5_4
|
||||
CreateGrid5x4(void);
|
||||
|
||||
main_LargeStruct
|
||||
CreateLargeStruct(int64_t id, GoString name);
|
||||
|
||||
Array_int32_t_4
|
||||
CreateMatrix1D(void);
|
||||
|
||||
Array_int32_t_3_4
|
||||
CreateMatrix2D(void);
|
||||
|
||||
Array_uint8_t_2_3_4
|
||||
CreateMatrix3D(void);
|
||||
|
||||
main_Node*
|
||||
CreateNode(intptr_t data);
|
||||
|
||||
main_SmallStruct
|
||||
CreateSmallStruct(int8_t id, _Bool flag);
|
||||
|
||||
C_XType
|
||||
CreateXType(int32_t id, GoString name, double value, _Bool flag);
|
||||
|
||||
void
|
||||
HelloWorld(void);
|
||||
|
||||
intptr_t
|
||||
LinkNodes(main_Node* first, main_Node* second);
|
||||
|
||||
GoString
|
||||
MultipleParams(int8_t a, uint16_t b, int32_t c, uint64_t d, float e, double f, GoString g, _Bool h);
|
||||
|
||||
int32_t
|
||||
NoParamNames(int8_t, int16_t, _Bool);
|
||||
|
||||
intptr_t
|
||||
NoParams(void);
|
||||
|
||||
void
|
||||
NoReturn(GoString message);
|
||||
|
||||
intptr_t
|
||||
OneParam(intptr_t x);
|
||||
|
||||
_Bool
|
||||
ProcessBool(_Bool b);
|
||||
|
||||
int32_t
|
||||
ProcessComplexData(main_ComplexData data);
|
||||
|
||||
float
|
||||
ProcessFloat32(float x);
|
||||
|
||||
double
|
||||
ProcessFloat64(double x);
|
||||
|
||||
double
|
||||
ProcessGrid5x4(double grid[5][4]);
|
||||
|
||||
intptr_t
|
||||
ProcessInt(intptr_t x);
|
||||
|
||||
int16_t
|
||||
ProcessInt16(int16_t x);
|
||||
|
||||
int32_t
|
||||
ProcessInt32(int32_t x);
|
||||
|
||||
int64_t
|
||||
ProcessInt64(int64_t x);
|
||||
|
||||
int8_t
|
||||
ProcessInt8(int8_t x);
|
||||
|
||||
intptr_t
|
||||
ProcessIntArray(intptr_t* arr);
|
||||
|
||||
intptr_t
|
||||
ProcessIntChannel(GoChan ch);
|
||||
|
||||
intptr_t
|
||||
ProcessIntSlice(GoSlice slice);
|
||||
|
||||
intptr_t
|
||||
ProcessInterface(GoInterface i);
|
||||
|
||||
int64_t
|
||||
ProcessLargeStruct(main_LargeStruct ls);
|
||||
|
||||
main_LargeStruct*
|
||||
ProcessLargeStructPtr(main_LargeStruct* ls);
|
||||
|
||||
int32_t
|
||||
ProcessMatrix2D(int32_t matrix[3][4]);
|
||||
|
||||
uint32_t
|
||||
ProcessMatrix3D(uint8_t cube[2][3][4]);
|
||||
|
||||
main_MyInt
|
||||
ProcessMyInt(main_MyInt x);
|
||||
|
||||
main_MyString
|
||||
ProcessMyString(main_MyString s);
|
||||
|
||||
main_SmallStruct
|
||||
ProcessSmallStruct(main_SmallStruct s);
|
||||
|
||||
main_SmallStruct*
|
||||
ProcessSmallStructPtr(main_SmallStruct* s);
|
||||
|
||||
GoString
|
||||
ProcessString(GoString s);
|
||||
|
||||
intptr_t
|
||||
ProcessStringMap(GoMap m);
|
||||
|
||||
double
|
||||
ProcessThreeUnnamedParams(intptr_t a, GoString s, _Bool b);
|
||||
|
||||
uintptr_t
|
||||
ProcessUint(uintptr_t x);
|
||||
|
||||
uint16_t
|
||||
ProcessUint16(uint16_t x);
|
||||
|
||||
uint32_t
|
||||
ProcessUint32(uint32_t x);
|
||||
|
||||
uint64_t
|
||||
ProcessUint64(uint64_t x);
|
||||
|
||||
uint8_t
|
||||
ProcessUint8(uint8_t x);
|
||||
|
||||
uintptr_t
|
||||
ProcessUintptr(uintptr_t x);
|
||||
|
||||
void*
|
||||
ProcessUnsafePointer(void* p);
|
||||
|
||||
intptr_t
|
||||
ProcessWithIntCallback(intptr_t x, main_IntCallback callback);
|
||||
|
||||
GoString
|
||||
ProcessWithStringCallback(GoString s, main_StringCallback callback);
|
||||
|
||||
intptr_t
|
||||
ProcessWithVoidCallback(main_VoidCallback callback);
|
||||
|
||||
C_XType
|
||||
ProcessXType(C_XType x);
|
||||
|
||||
C_XType*
|
||||
ProcessXTypePtr(C_XType* x);
|
||||
|
||||
double
|
||||
ThreeParams(int32_t a, double b, _Bool c);
|
||||
|
||||
intptr_t
|
||||
TraverseNodes(main_Node* head);
|
||||
|
||||
GoString
|
||||
TwoParams(intptr_t a, GoString b);
|
||||
|
||||
void
|
||||
github_com_goplus_llgo__demo_go_export_init(void) GO_SYMBOL_RENAME("github.com/goplus/llgo/_demo/go/export.init")
|
||||
|
||||
void
|
||||
github_com_goplus_llgo_runtime_abi_init(void) GO_SYMBOL_RENAME("github.com/goplus/llgo/runtime/abi.init")
|
||||
|
||||
void
|
||||
github_com_goplus_llgo_runtime_internal_clite_init(void) GO_SYMBOL_RENAME("github.com/goplus/llgo/runtime/internal/clite.init")
|
||||
|
||||
void
|
||||
github_com_goplus_llgo_runtime_internal_clite_bdwgc_init(void) GO_SYMBOL_RENAME("github.com/goplus/llgo/runtime/internal/clite/bdwgc.init")
|
||||
|
||||
void
|
||||
github_com_goplus_llgo_runtime_internal_clite_bitcast_init(void) GO_SYMBOL_RENAME("github.com/goplus/llgo/runtime/internal/clite/bitcast.init")
|
||||
|
||||
void
|
||||
github_com_goplus_llgo_runtime_internal_clite_debug_init(void) GO_SYMBOL_RENAME("github.com/goplus/llgo/runtime/internal/clite/debug.init")
|
||||
|
||||
void
|
||||
github_com_goplus_llgo_runtime_internal_clite_pthread_init(void) GO_SYMBOL_RENAME("github.com/goplus/llgo/runtime/internal/clite/pthread.init")
|
||||
|
||||
void
|
||||
github_com_goplus_llgo_runtime_internal_clite_pthread_sync_init(void) GO_SYMBOL_RENAME("github.com/goplus/llgo/runtime/internal/clite/pthread/sync.init")
|
||||
|
||||
void
|
||||
github_com_goplus_llgo_runtime_internal_runtime_goarch_init(void) GO_SYMBOL_RENAME("github.com/goplus/llgo/runtime/internal/runtime/goarch.init")
|
||||
|
||||
void
|
||||
github_com_goplus_llgo_runtime_internal_runtime_math_init(void) GO_SYMBOL_RENAME("github.com/goplus/llgo/runtime/internal/runtime/math.init")
|
||||
|
||||
void
|
||||
github_com_goplus_llgo_runtime_internal_runtime_init(void) GO_SYMBOL_RENAME("github.com/goplus/llgo/runtime/internal/runtime.init")
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LIBEXPORT_H_ */
|
||||
278
_demo/go/export/test.sh
Executable file
278
_demo/go/export/test.sh
Executable file
@@ -0,0 +1,278 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Test script for C header generation in different build modes
|
||||
# This script tests the header generation functionality with various buildmode options
|
||||
|
||||
set -e # Exit on any error
|
||||
|
||||
# Get script directory
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to print colored output
|
||||
print_status() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Function to check if file exists and is not empty
|
||||
check_file() {
|
||||
local file="$1"
|
||||
local description="$2"
|
||||
|
||||
if [[ -f "$file" ]]; then
|
||||
if [[ -s "$file" ]]; then
|
||||
print_status "$description exists and is not empty"
|
||||
return 0
|
||||
else
|
||||
print_error "$description exists but is empty"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
print_error "$description does not exist"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to compare header with expected content
|
||||
compare_header() {
|
||||
local header_file="$1"
|
||||
local expected_file="$2"
|
||||
local test_name="$3"
|
||||
|
||||
if [[ -f "$expected_file" ]]; then
|
||||
if diff -q "$header_file" "$expected_file" >/dev/null 2>&1; then
|
||||
print_status "$test_name: Header content matches expected"
|
||||
return 0
|
||||
else
|
||||
print_warning "$test_name: Header content differs from expected"
|
||||
print_warning "Run 'diff $header_file $expected_file' to see differences"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
print_warning "$test_name: No expected file found at $expected_file"
|
||||
print_status "Generated header content:"
|
||||
echo "--- START OF HEADER ---"
|
||||
cat "$header_file"
|
||||
echo "--- END OF HEADER ---"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to cleanup generated files
|
||||
cleanup() {
|
||||
local files=("$@")
|
||||
for file in "${files[@]}"; do
|
||||
if [[ -f "$file" ]]; then
|
||||
rm -f "$file"
|
||||
print_status "Cleaned up $file"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Check if llgo.sh exists
|
||||
LLGO_SCRIPT="../../../llgo.sh"
|
||||
if [[ ! -f "$LLGO_SCRIPT" ]]; then
|
||||
print_error "llgo.sh not found at $LLGO_SCRIPT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_status "Starting C header generation tests..."
|
||||
print_status "Working directory: $SCRIPT_DIR"
|
||||
|
||||
echo ""
|
||||
|
||||
# Test 1: c-shared mode
|
||||
print_status "=== Test 2: Building with -buildmode c-shared ==="
|
||||
if $LLGO_SCRIPT build -buildmode c-shared -o export .; then
|
||||
print_status "Build succeeded"
|
||||
|
||||
# Check generated files (different extensions on different platforms)
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
# macOS
|
||||
check_file "libexport.dylib" "Dynamic library (libexport.dylib)"
|
||||
SHARED_LIB="libexport.dylib"
|
||||
else
|
||||
# Linux and others
|
||||
check_file "libexport.so" "Dynamic library (libexport.so)"
|
||||
SHARED_LIB="libexport.so"
|
||||
fi
|
||||
|
||||
check_file "libexport.h" "C header (libexport.h)"
|
||||
|
||||
# Compare with expected header if it exists
|
||||
if [[ -f "libexport.h" ]]; then
|
||||
compare_header "libexport.h" "libexport.h.want" "c-shared"
|
||||
fi
|
||||
|
||||
# Test C demo with shared library
|
||||
print_status "=== Testing C demo with shared library ==="
|
||||
if cd use; then
|
||||
if LINK_TYPE=shared make clean && LINK_TYPE=shared make; then
|
||||
print_status "C demo build succeeded with shared library"
|
||||
if LINK_TYPE=shared make run; then
|
||||
print_status "C demo execution succeeded with shared library"
|
||||
else
|
||||
print_warning "C demo execution failed with shared library"
|
||||
fi
|
||||
else
|
||||
print_warning "C demo build failed with shared library"
|
||||
fi
|
||||
cd ..
|
||||
else
|
||||
print_error "Failed to enter use directory"
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
cleanup "$SHARED_LIB" "libexport.h"
|
||||
else
|
||||
print_error "Build failed for c-shared mode"
|
||||
fi
|
||||
|
||||
# Test 2: c-archive mode
|
||||
print_status "=== Test 1: Building with -buildmode c-archive ==="
|
||||
if $LLGO_SCRIPT build -buildmode c-archive -o export .; then
|
||||
print_status "Build succeeded"
|
||||
|
||||
# Check generated files
|
||||
check_file "libexport.a" "Static library (libexport.a)"
|
||||
check_file "libexport.h" "C header (libexport.h)"
|
||||
|
||||
# Compare with expected header if it exists
|
||||
if [[ -f "libexport.h" ]]; then
|
||||
compare_header "libexport.h" "libexport.h.want" "c-archive"
|
||||
fi
|
||||
|
||||
# Test C demo with static library
|
||||
print_status "=== Testing C demo with static library ==="
|
||||
if cd use; then
|
||||
if make clean && make; then
|
||||
print_status "C demo build succeeded with static library"
|
||||
if make run; then
|
||||
print_status "C demo execution succeeded with static library"
|
||||
else
|
||||
print_warning "C demo execution failed with static library"
|
||||
fi
|
||||
else
|
||||
print_warning "C demo build failed with static library"
|
||||
fi
|
||||
cd ..
|
||||
else
|
||||
print_error "Failed to enter use directory"
|
||||
fi
|
||||
|
||||
# # Cleanup
|
||||
# cleanup "libexport.a" "libexport.h"
|
||||
else
|
||||
print_error "Build failed for c-archive mode"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# TODO(lijie): Uncomment if https://github.com/goplus/llgo/pull/1268 merged
|
||||
# # Test 3: ESP32 target with c-archive mode
|
||||
# print_status "=== Test 3: Building with -target esp32 -buildmode c-archive ==="
|
||||
# if $LLGO_SCRIPT build -target esp32 -buildmode c-archive -o export .; then
|
||||
# print_status "Build succeeded"
|
||||
|
||||
# # Check generated files
|
||||
# check_file "libexport.a" "Static library for ESP32 (libexport.a)"
|
||||
# check_file "libexport.h" "C header for ESP32 (libexport.h)"
|
||||
|
||||
# # Compare with expected header if it exists
|
||||
# if [[ -f "libexport.h" ]]; then
|
||||
# compare_header "libexport.h" "libexport.h.want" "esp32-c-archive"
|
||||
# fi
|
||||
|
||||
# # Don't cleanup ESP32 files - keep them for inspection
|
||||
# print_status "ESP32 build files kept for inspection"
|
||||
# else
|
||||
# print_error "Build failed for ESP32 target"
|
||||
# fi
|
||||
|
||||
# echo ""
|
||||
|
||||
# Test 3: Go export demo execution
|
||||
print_status "=== Test 3: Running Go export demo ==="
|
||||
if go run export.go > /tmp/go_export_output.log 2>&1; then
|
||||
print_status "Go export demo execution succeeded"
|
||||
|
||||
# Check if output contains expected success indicators
|
||||
if grep -q "✓" /tmp/go_export_output.log; then
|
||||
SUCCESS_COUNT=$(grep -c "✓" /tmp/go_export_output.log)
|
||||
print_status "All $SUCCESS_COUNT assertions passed in Go export demo"
|
||||
else
|
||||
print_warning "No assertion markers found in Go export demo output"
|
||||
fi
|
||||
|
||||
# Show key output lines
|
||||
print_status "Go export demo output summary:"
|
||||
if grep -q "ASSERTION FAILED" /tmp/go_export_output.log; then
|
||||
print_error "Found assertion failures in Go export demo"
|
||||
grep "ASSERTION FAILED" /tmp/go_export_output.log
|
||||
else
|
||||
print_status " ✅ No assertion failures detected"
|
||||
echo " 📊 First few lines of output:"
|
||||
head -5 /tmp/go_export_output.log | sed 's/^/ /'
|
||||
echo " 📊 Last few lines of output:"
|
||||
tail -5 /tmp/go_export_output.log | sed 's/^/ /'
|
||||
fi
|
||||
else
|
||||
print_error "Go export demo execution failed"
|
||||
print_error "Error output:"
|
||||
cat /tmp/go_export_output.log | sed 's/^/ /'
|
||||
fi
|
||||
|
||||
# Cleanup temporary file
|
||||
rm -f /tmp/go_export_output.log
|
||||
|
||||
echo ""
|
||||
|
||||
# Final summary
|
||||
print_status "=== Test Summary ==="
|
||||
if [[ -f "libexport.a" ]] && [[ -f "libexport.h" ]]; then
|
||||
print_status "All tests completed successfully:"
|
||||
print_status " ✅ Go export demo execution with assertions"
|
||||
print_status " ✅ C header generation (c-archive and c-shared modes)"
|
||||
print_status " ✅ C demo compilation and execution"
|
||||
print_status " ✅ Cross-platform symbol renaming"
|
||||
print_status " ✅ Init function export and calling"
|
||||
print_status " ✅ Function callback types with proper typedef syntax"
|
||||
print_status " ✅ Multidimensional array parameter handling"
|
||||
print_status ""
|
||||
print_status "Final files available:"
|
||||
print_status " - libexport.a (static library)"
|
||||
print_status " - libexport.h (C header file)"
|
||||
print_status " - use/main.out (C demo executable)"
|
||||
|
||||
echo ""
|
||||
echo "==================="
|
||||
else
|
||||
print_error "Some tests may have failed. Check the output above."
|
||||
fi
|
||||
|
||||
# Show file sizes for reference
|
||||
if [[ -f "libexport.a" ]]; then
|
||||
SIZE=$(wc -c < libexport.a)
|
||||
print_status "Static library size: $SIZE bytes"
|
||||
fi
|
||||
|
||||
if [[ -f "libexport.h" ]]; then
|
||||
LINES=$(wc -l < libexport.h)
|
||||
print_status "Header file lines: $LINES"
|
||||
fi
|
||||
|
||||
print_status "C header generation and demo tests completed!"
|
||||
84
_demo/go/export/use/Makefile
Normal file
84
_demo/go/export/use/Makefile
Normal file
@@ -0,0 +1,84 @@
|
||||
# Makefile for C demo using Go exported library
|
||||
# Use LINK_TYPE environment variable to choose library type:
|
||||
# LINK_TYPE=static - Link with static library (default)
|
||||
# LINK_TYPE=shared - Link with shared library
|
||||
|
||||
CC = clang
|
||||
CFLAGS = -Wall -Wextra -std=c99
|
||||
INCLUDES = -I..
|
||||
TARGET = main.out
|
||||
SOURCES = main.c
|
||||
HEADER = ../libexport.h
|
||||
|
||||
# Default to static linking
|
||||
LINK_TYPE ?= static
|
||||
|
||||
# Platform detection
|
||||
UNAME_S := $(shell uname -s)
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
SHARED_EXT = dylib
|
||||
PLATFORM_LIBS =
|
||||
else
|
||||
SHARED_EXT = so
|
||||
PLATFORM_LIBS = $(shell pkg-config --libs libunwind 2>/dev/null || echo -lunwind)
|
||||
endif
|
||||
|
||||
# Library and flags based on link type
|
||||
ifeq ($(LINK_TYPE),shared)
|
||||
BUILDMODE = c-shared
|
||||
LIBRARY = ../libexport.$(SHARED_EXT)
|
||||
LDFLAGS = -L.. -lexport -lpthread -lm $(shell pkg-config --libs bdw-gc || echo -lgc) $(PLATFORM_LIBS)
|
||||
BUILD_MSG = "Building Go shared library..."
|
||||
LINK_MSG = "Linking with shared library..."
|
||||
else
|
||||
BUILDMODE = c-archive
|
||||
LIBRARY = ../libexport.a
|
||||
LDFLAGS = $(LIBRARY) -lpthread -lm $(shell pkg-config --libs bdw-gc || echo -lgc) $(PLATFORM_LIBS)
|
||||
BUILD_MSG = "Building Go static library..."
|
||||
LINK_MSG = "Linking with static library..."
|
||||
endif
|
||||
|
||||
.PHONY: all clean run build-go
|
||||
|
||||
all: build-go $(TARGET)
|
||||
|
||||
# Build the Go library first
|
||||
build-go:
|
||||
@echo $(BUILD_MSG)
|
||||
cd .. && ../../../llgo.sh build -buildmode $(BUILDMODE) -o export .
|
||||
|
||||
# Build the C executable
|
||||
$(TARGET): $(SOURCES) $(LIBRARY) $(HEADER)
|
||||
@echo $(LINK_MSG)
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -o $(TARGET) $(SOURCES) $(LDFLAGS)
|
||||
|
||||
# Run the executable
|
||||
run: $(TARGET)
|
||||
@echo "Running C demo..."
|
||||
ifeq ($(LINK_TYPE),shared)
|
||||
@echo "Setting library path for shared library..."
|
||||
LD_LIBRARY_PATH=.. DYLD_LIBRARY_PATH=.. ./$(TARGET)
|
||||
else
|
||||
./$(TARGET)
|
||||
endif
|
||||
|
||||
# Clean build artifacts
|
||||
clean:
|
||||
rm -f $(TARGET)
|
||||
rm -f ../libexport.a ../libexport.h ../libexport.so ../libexport.dylib
|
||||
|
||||
# Help target
|
||||
help:
|
||||
@echo "Available targets:"
|
||||
@echo " all - Build Go library and C executable"
|
||||
@echo " build-go - Build only the Go library"
|
||||
@echo " run - Build and run the C demo"
|
||||
@echo " clean - Clean all build artifacts"
|
||||
@echo " help - Show this help message"
|
||||
@echo ""
|
||||
@echo "Environment variables:"
|
||||
@echo " LINK_TYPE - Library type: 'static' (default) or 'shared'"
|
||||
@echo ""
|
||||
@echo "Examples:"
|
||||
@echo " make run # Use static library"
|
||||
@echo " LINK_TYPE=shared make run # Use shared library"
|
||||
237
_demo/go/export/use/main.c
Normal file
237
_demo/go/export/use/main.c
Normal file
@@ -0,0 +1,237 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
#include "../libexport.h"
|
||||
|
||||
int main() {
|
||||
printf("=== C Export Demo ===\n");
|
||||
fflush(stdout); // Force output
|
||||
|
||||
// Initialize packages - call init functions first
|
||||
github_com_goplus_llgo__demo_go_export_c_init();
|
||||
github_com_goplus_llgo__demo_go_export_init();
|
||||
|
||||
// Test HelloWorld
|
||||
HelloWorld();
|
||||
printf("\n");
|
||||
|
||||
// Test small struct
|
||||
main_SmallStruct small = CreateSmallStruct(5, 1); // 1 for true
|
||||
printf("Small struct: %d %d\n", small.ID, small.Flag);
|
||||
|
||||
main_SmallStruct processed = ProcessSmallStruct(small);
|
||||
printf("Processed small: %d %d\n", processed.ID, processed.Flag);
|
||||
|
||||
main_SmallStruct* ptrSmall = ProcessSmallStructPtr(&small);
|
||||
if (ptrSmall != NULL) {
|
||||
printf("Ptr small: %d %d\n", ptrSmall->ID, ptrSmall->Flag);
|
||||
}
|
||||
|
||||
// Test large struct - create GoString for name parameter
|
||||
GoString name = {"test_large", 10}; // name and length
|
||||
main_LargeStruct large = CreateLargeStruct(12345, name);
|
||||
printf("Large struct ID: %" PRId64 "\n", large.ID);
|
||||
|
||||
int64_t total = ProcessLargeStruct(large);
|
||||
printf("Large struct total: %" PRId64 "\n", total);
|
||||
|
||||
main_LargeStruct* ptrLarge = ProcessLargeStructPtr(&large);
|
||||
if (ptrLarge != NULL) {
|
||||
printf("Ptr large ID: %" PRId64 "\n", ptrLarge->ID);
|
||||
}
|
||||
|
||||
// Test self-referential struct
|
||||
main_Node* node1 = CreateNode(100);
|
||||
main_Node* node2 = CreateNode(200);
|
||||
int link_result = LinkNodes(node1, node2);
|
||||
assert(link_result == 300); // LinkNodes returns 100 + 200 = 300
|
||||
printf("LinkNodes result: %d\n", link_result);
|
||||
|
||||
int count = TraverseNodes(node1);
|
||||
assert(count == 2); // Should traverse 2 nodes
|
||||
printf("Node count: %d\n", count);
|
||||
|
||||
// Test basic types with assertions
|
||||
assert(ProcessBool(1) == 0); // ProcessBool(true) returns !true = false
|
||||
printf("Bool: %d\n", ProcessBool(1));
|
||||
|
||||
assert(ProcessInt8(10) == 11); // ProcessInt8(x) returns x + 1
|
||||
printf("Int8: %d\n", ProcessInt8(10));
|
||||
|
||||
assert(ProcessUint8(10) == 11); // ProcessUint8(x) returns x + 1
|
||||
printf("Uint8: %d\n", ProcessUint8(10));
|
||||
|
||||
assert(ProcessInt16(10) == 20); // ProcessInt16(x) returns x * 2
|
||||
printf("Int16: %d\n", ProcessInt16(10));
|
||||
|
||||
assert(ProcessUint16(10) == 20); // ProcessUint16(x) returns x * 2
|
||||
printf("Uint16: %d\n", ProcessUint16(10));
|
||||
|
||||
assert(ProcessInt32(10) == 30); // ProcessInt32(x) returns x * 3
|
||||
printf("Int32: %d\n", ProcessInt32(10));
|
||||
|
||||
assert(ProcessUint32(10) == 30); // ProcessUint32(x) returns x * 3
|
||||
printf("Uint32: %u\n", ProcessUint32(10));
|
||||
|
||||
assert(ProcessInt64(10) == 40); // ProcessInt64(x) returns x * 4
|
||||
printf("Int64: %" PRId64 "\n", ProcessInt64(10));
|
||||
|
||||
assert(ProcessUint64(10) == 40); // ProcessUint64(x) returns x * 4
|
||||
printf("Uint64: %" PRIu64 "\n", ProcessUint64(10));
|
||||
|
||||
assert(ProcessInt(10) == 110); // ProcessInt(x) returns x * 11
|
||||
printf("Int: %ld\n", ProcessInt(10));
|
||||
|
||||
assert(ProcessUint(10) == 210); // ProcessUint(x) returns x * 21
|
||||
printf("Uint: %lu\n", ProcessUint(10));
|
||||
|
||||
assert(ProcessUintptr(0x1000) == 4396); // ProcessUintptr(x) returns x + 300 = 4096 + 300
|
||||
printf("Uintptr: %lu\n", ProcessUintptr(0x1000));
|
||||
|
||||
// Float comparisons with tolerance
|
||||
float f32_result = ProcessFloat32(3.14f);
|
||||
assert(f32_result > 4.7f && f32_result < 4.72f); // ProcessFloat32(x) returns x * 1.5 ≈ 4.71
|
||||
printf("Float32: %f\n", f32_result);
|
||||
|
||||
double f64_result = ProcessFloat64(3.14);
|
||||
assert(f64_result > 7.84 && f64_result < 7.86); // ProcessFloat64(x) returns x * 2.5 ≈ 7.85
|
||||
printf("Float64: %f\n", f64_result);
|
||||
|
||||
// Test unsafe pointer
|
||||
int test_val = 42;
|
||||
void* ptr_result = ProcessUnsafePointer(&test_val);
|
||||
printf("UnsafePointer: %p\n", ptr_result);
|
||||
|
||||
// Test named types
|
||||
main_MyInt myInt = ProcessMyInt(42);
|
||||
printf("MyInt: %ld\n", (long)myInt);
|
||||
|
||||
// Test arrays
|
||||
intptr_t arr[5] = {1, 2, 3, 4, 5};
|
||||
printf("Array sum: %ld\n", ProcessIntArray(arr));
|
||||
|
||||
// Test complex data with multidimensional arrays
|
||||
main_ComplexData complex = CreateComplexData();
|
||||
printf("Complex data matrix sum: %" PRId32 "\n", ProcessComplexData(complex));
|
||||
|
||||
// Test interface - this is more complex in C, we'll skip for now
|
||||
printf("Interface test skipped (complex in C)\n");
|
||||
|
||||
// Test various parameter counts
|
||||
assert(NoParams() == 42); // NoParams() always returns 42
|
||||
printf("NoParams: %ld\n", NoParams());
|
||||
|
||||
assert(OneParam(5) == 10); // OneParam(x) returns x * 2
|
||||
printf("OneParam: %ld\n", OneParam(5));
|
||||
|
||||
assert(ThreeParams(10, 2.5, 1) == 25.0); // ThreeParams calculates result
|
||||
printf("ThreeParams: %f\n", ThreeParams(10, 2.5, 1)); // 1 for true
|
||||
|
||||
// Test ProcessThreeUnnamedParams - now uses all parameters
|
||||
GoString test_str = {"hello", 5};
|
||||
double unnamed_result = ProcessThreeUnnamedParams(10, test_str, 1);
|
||||
assert(unnamed_result == 22.5); // (10 + 5) * 1.5 = 22.5
|
||||
printf("ProcessThreeUnnamedParams: %f\n", unnamed_result);
|
||||
|
||||
// Test ProcessWithVoidCallback - now returns int
|
||||
int void_callback_result = ProcessWithVoidCallback(NULL);
|
||||
assert(void_callback_result == 456); // Returns 456 when callback is nil
|
||||
printf("ProcessWithVoidCallback(NULL): %d\n", void_callback_result);
|
||||
|
||||
// Test NoParamNames - function with unnamed parameters
|
||||
int32_t no_names_result = NoParamNames(5, 10, 0);
|
||||
assert(no_names_result == 789); // Returns fixed value 789
|
||||
printf("NoParamNames: %d\n", no_names_result);
|
||||
|
||||
// Test XType from c package - create GoString for name parameter
|
||||
GoString xname = {"test_x", 6}; // name and length
|
||||
C_XType xtype = CreateXType(42, xname, 3.14, 1); // 1 for true
|
||||
printf("XType: %d %f %d\n", xtype.ID, xtype.Value, xtype.Flag);
|
||||
|
||||
C_XType processedX = ProcessXType(xtype);
|
||||
printf("Processed XType: %d %f %d\n", processedX.ID, processedX.Value, processedX.Flag);
|
||||
|
||||
C_XType* ptrX = ProcessXTypePtr(&xtype);
|
||||
if (ptrX != NULL) {
|
||||
printf("Ptr XType: %d %f %d\n", ptrX->ID, ptrX->Value, ptrX->Flag);
|
||||
}
|
||||
|
||||
// Test multidimensional arrays
|
||||
printf("\n=== Multidimensional Array Tests ===\n");
|
||||
|
||||
// Create and test 2D matrix [3][4]
|
||||
// Note: CreateMatrix2D returns [3][4]int32, but function returns need special handling in C
|
||||
printf("Testing 2D matrix functions...\n");
|
||||
|
||||
// Create a test 2D matrix [3][4]int32
|
||||
int32_t test_matrix[3][4] = {
|
||||
{1, 2, 3, 4},
|
||||
{5, 6, 7, 8},
|
||||
{9, 10, 11, 12}
|
||||
};
|
||||
int32_t matrix_sum = ProcessMatrix2D(test_matrix);
|
||||
assert(matrix_sum == 78); // Sum of 1+2+3+...+12 = 78
|
||||
printf("Matrix2D sum: %d\n", matrix_sum);
|
||||
|
||||
// Create a test 3D cube [2][3][4]uint8
|
||||
uint8_t test_cube[2][3][4];
|
||||
uint8_t val = 1;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
for (int k = 0; k < 4; k++) {
|
||||
test_cube[i][j][k] = val++;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t cube_sum = ProcessMatrix3D(test_cube);
|
||||
assert(cube_sum == 300); // Sum of 1+2+3+...+24 = 300
|
||||
printf("Matrix3D (cube) sum: %u\n", cube_sum);
|
||||
|
||||
// Create a test 5x4 grid [5][4]double
|
||||
double test_grid[5][4];
|
||||
double grid_val = 1.0;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
test_grid[i][j] = grid_val;
|
||||
grid_val += 0.5;
|
||||
}
|
||||
}
|
||||
double grid_sum = ProcessGrid5x4(test_grid);
|
||||
assert(grid_sum == 115.0); // Sum of 1.0+1.5+2.0+...+10.5 = 115.0
|
||||
printf("Grid5x4 sum: %f\n", grid_sum);
|
||||
|
||||
// Test functions that return multidimensional arrays (as multi-level pointers)
|
||||
printf("\n=== Testing Return Value Functions ===\n");
|
||||
|
||||
// Test CreateMatrix1D() which returns Array_int32_t_4
|
||||
printf("About to call CreateMatrix1D()...\n");
|
||||
fflush(stdout);
|
||||
Array_int32_t_4 matrix1d = CreateMatrix1D();
|
||||
printf("CreateMatrix1D() call completed\n");
|
||||
printf("CreateMatrix1D() returned struct, first element: %d\n", matrix1d.data[0]);
|
||||
|
||||
// Test CreateMatrix2D() which returns Array_int32_t_3_4
|
||||
printf("About to call CreateMatrix2D()...\n");
|
||||
fflush(stdout);
|
||||
Array_int32_t_3_4 matrix2d = CreateMatrix2D();
|
||||
printf("CreateMatrix2D() call completed\n");
|
||||
printf("CreateMatrix2D() returned struct, first element: %d\n", matrix2d.data[0][0]);
|
||||
|
||||
// Test CreateMatrix3D() which returns Array_uint8_t_2_3_4
|
||||
Array_uint8_t_2_3_4 cube = CreateMatrix3D();
|
||||
printf("CreateMatrix3D() returned struct, first element: %u\n", cube.data[0][0][0]);
|
||||
|
||||
// Test CreateGrid5x4() which returns Array_double_5_4
|
||||
Array_double_5_4 grid = CreateGrid5x4();
|
||||
printf("CreateGrid5x4() returned struct, first element: %f\n", grid.data[0][0]);
|
||||
|
||||
// Test NoReturn function
|
||||
// Note: This function takes a string parameter which is complex to pass from C
|
||||
// We'll skip it for now or pass a simple string if the binding allows
|
||||
printf("NoReturn test skipped (string parameter)\n");
|
||||
|
||||
printf("C demo completed!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
3
_demo/go/go.mod
Normal file
3
_demo/go/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module github.com/goplus/llgo/_demo/go
|
||||
|
||||
go 1.20
|
||||
0
_demo/go/go.sum
Normal file
0
_demo/go/go.sum
Normal file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user