mirror of
https://github.com/mirror/tinycc.git
synced 2026-08-26 11:43:27 +08:00
Compare commits
623 Commits
release_0_
...
release_0_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5e22108a0 | ||
|
|
bfde339b8c | ||
|
|
cec76c8b8a | ||
|
|
108b287665 | ||
|
|
0928761257 | ||
|
|
c4397b2b02 | ||
|
|
b9f089fc4a | ||
|
|
762a43877b | ||
|
|
99b801dafc | ||
|
|
b4656f3191 | ||
|
|
b1a8233562 | ||
|
|
062efe6ab8 | ||
|
|
944627c479 | ||
|
|
e298f60838 | ||
|
|
a4cbd9b002 | ||
|
|
f9ac201377 | ||
|
|
af4b27f0fd | ||
|
|
f6cfaa6d25 | ||
|
|
05108a3b0a | ||
|
|
829655949b | ||
|
|
8042121d74 | ||
|
|
d6d7686b60 | ||
|
|
4b8e7f1f39 | ||
|
|
7a477d70ca | ||
|
|
92024ab07a | ||
|
|
d5f4df09ff | ||
|
|
60cf64612c | ||
|
|
6c4d3244da | ||
|
|
e0aee4f455 | ||
|
|
60e647f856 | ||
|
|
248dc67506 | ||
|
|
4b539aa67d | ||
|
|
97c279f5ea | ||
|
|
82bcbd027f | ||
|
|
3186455599 | ||
|
|
4c2941d248 | ||
|
|
263dc93cfa | ||
|
|
f715207249 | ||
|
|
61a4fd1d6e | ||
|
|
f7f6025bd1 | ||
|
|
506193724f | ||
|
|
6f4983af5b | ||
|
|
ae33c30b49 | ||
|
|
2f6b8469cc | ||
|
|
370547a550 | ||
|
|
981eb84d8a | ||
|
|
505329b5b3 | ||
|
|
93785149ed | ||
|
|
1b1e7ee1fd | ||
|
|
913cd6270b | ||
|
|
828ccde9fc | ||
|
|
b7e75ccdb0 | ||
|
|
17cf0dcf70 | ||
|
|
6ccee6edb3 | ||
|
|
5fa135f9eb | ||
|
|
01e1eecdbe | ||
|
|
52947e5844 | ||
|
|
bcac413c30 | ||
|
|
0f81512d7d | ||
|
|
f3e5649150 | ||
|
|
f63c750942 | ||
|
|
de35a3389f | ||
|
|
f8cde52984 | ||
|
|
b89793d10a | ||
|
|
6b6eea60f3 | ||
|
|
c5892fe4f5 | ||
|
|
2daf8b96a8 | ||
|
|
f7b417723e | ||
|
|
a4e630c7d9 | ||
|
|
8c56b0cf90 | ||
|
|
60a3ff5f2c | ||
|
|
5e7954b408 | ||
|
|
ea583f7b8a | ||
|
|
59e18aee0e | ||
|
|
0a8c7d143e | ||
|
|
2358b378b3 | ||
|
|
e92dbe4686 | ||
|
|
eb028a8f42 | ||
|
|
fc574f1498 | ||
|
|
63193d1794 | ||
|
|
8eb92e6052 | ||
|
|
e79281f58e | ||
|
|
7667a8887a | ||
|
|
8adfb4a419 | ||
|
|
017bbbfee1 | ||
|
|
d7264e0218 | ||
|
|
ba49862de6 | ||
|
|
9c9ca2032b | ||
|
|
5ebc6a964d | ||
|
|
b174399340 | ||
|
|
3f09b90d21 | ||
|
|
d815896d4c | ||
|
|
a55ecf6d2c | ||
|
|
031ff872be | ||
|
|
dbeb4faf21 | ||
|
|
efd9d92b7c | ||
|
|
43a11a7ed1 | ||
|
|
c4a18f47a2 | ||
|
|
05b02a5581 | ||
|
|
8d90205fd9 | ||
|
|
168aed4984 | ||
|
|
4744269494 | ||
|
|
6eec931038 | ||
|
|
15a315f4a5 | ||
|
|
e2212738d4 | ||
|
|
ab24aaeca3 | ||
|
|
b2a02961b4 | ||
|
|
e79c3533ec | ||
|
|
40a54c4399 | ||
|
|
5d648485bd | ||
|
|
cffb7af9f9 | ||
|
|
646b51833f | ||
|
|
1af3bca4ea | ||
|
|
3c986eeae3 | ||
|
|
14c99236da | ||
|
|
061b5799cc | ||
|
|
891dfcdf3f | ||
|
|
e07802e39d | ||
|
|
b0f08ace94 | ||
|
|
a7f010ee8a | ||
|
|
5eb64357b1 | ||
|
|
943574aba5 | ||
|
|
034dce4f04 | ||
|
|
fad68c9163 | ||
|
|
508df168f4 | ||
|
|
cf95ac399c | ||
|
|
85f6fad3a6 | ||
|
|
9966fd4eae | ||
|
|
c6630ef92a | ||
|
|
2fe7fd9e87 | ||
|
|
3d409b0889 | ||
|
|
ca38792df1 | ||
|
|
56e23984b9 | ||
|
|
c9a2fbaad1 | ||
|
|
d1694f7d7e | ||
|
|
ed9c6b132a | ||
|
|
d27a0b3548 | ||
|
|
09b98a42a3 | ||
|
|
d54e24cc0e | ||
|
|
240064c03b | ||
|
|
42c1b6ba38 | ||
|
|
b0ebcfa7ba | ||
|
|
2e7a1af5d5 | ||
|
|
ad5f3758c3 | ||
|
|
27d38bf23f | ||
|
|
32cd070c96 | ||
|
|
a42b029101 | ||
|
|
9a81dcab0a | ||
|
|
7f6095bfec | ||
|
|
bfb00494eb | ||
|
|
731e07f175 | ||
|
|
b56edc7b90 | ||
|
|
a2c71af1ea | ||
|
|
2daae0dc99 | ||
|
|
0394caf784 | ||
|
|
9ca9c82ff8 | ||
|
|
718fd591fa | ||
|
|
b068e29df7 | ||
|
|
4c0d70ab07 | ||
|
|
15f4ac2b1a | ||
|
|
1d0a5c2515 | ||
|
|
86ac6b9bee | ||
|
|
5c0a2366a3 | ||
|
|
6471ec0a2b | ||
|
|
f98c2306a0 | ||
|
|
32a411914b | ||
|
|
f1b5c2ef4f | ||
|
|
3c59f84240 | ||
|
|
ab936aeb8c | ||
|
|
5aaa067af4 | ||
|
|
4274c44de7 | ||
|
|
214564b1dc | ||
|
|
176876e5de | ||
|
|
16202e054f | ||
|
|
1c11b857fe | ||
|
|
2eee100c37 | ||
|
|
c52d79605a | ||
|
|
7fb0482a46 | ||
|
|
1736a71b71 | ||
|
|
53c5715cca | ||
|
|
3d25213c16 | ||
|
|
de54586d5b | ||
|
|
ae191c3a61 | ||
|
|
a35b3059bb | ||
|
|
a0db7162af | ||
|
|
5775911dad | ||
|
|
e343b1dfd4 | ||
|
|
d7a7c3769d | ||
|
|
6e13c35334 | ||
|
|
8ca8b08890 | ||
|
|
9527c4949f | ||
|
|
3ab269c56a | ||
|
|
9c25ed13b4 | ||
|
|
519a9040a1 | ||
|
|
83d57c06f4 | ||
|
|
5f99fe2ff1 | ||
|
|
2dd3fb103e | ||
|
|
ab7ed48ee8 | ||
|
|
bf374a5f23 | ||
|
|
74a24d77fd | ||
|
|
fd0cea8895 | ||
|
|
e844fb11c2 | ||
|
|
e6f3bf7f08 | ||
|
|
39a07cca58 | ||
|
|
5e5e29f8fd | ||
|
|
f115c12346 | ||
|
|
81cd0cf6fd | ||
|
|
9ffd77f18d | ||
|
|
0b6652003c | ||
|
|
76adc5770f | ||
|
|
5e954fef32 | ||
|
|
df9cce24a8 | ||
|
|
626a907451 | ||
|
|
b2f5ee9b2d | ||
|
|
339f961c11 | ||
|
|
9b52e16a50 | ||
|
|
d7d8458888 | ||
|
|
adc80009c8 | ||
|
|
8d107d9ffd | ||
|
|
aa80e5b1ff | ||
|
|
d483ab322f | ||
|
|
08083ddb21 | ||
|
|
d59bd8be8e | ||
|
|
af83993810 | ||
|
|
df4c0892f3 | ||
|
|
232650f8b3 | ||
|
|
5280293d6b | ||
|
|
4ccb5662cb | ||
|
|
45184e01d8 | ||
|
|
7b573dc239 | ||
|
|
436c1a734f | ||
|
|
c71798c376 | ||
|
|
cd3d1a45f3 | ||
|
|
38756b506f | ||
|
|
5cf5871aaf | ||
|
|
13121e220c | ||
|
|
d01f65ef93 | ||
|
|
f8656fbc3c | ||
|
|
27a428cd0f | ||
|
|
a03346c06e | ||
|
|
571465d32b | ||
|
|
4d6a4a26e0 | ||
|
|
a6775fc154 | ||
|
|
ca6ff4fada | ||
|
|
38de06e334 | ||
|
|
31ca000d72 | ||
|
|
cb2138f8b0 | ||
|
|
3511e6e2a8 | ||
|
|
330d2ee0fa | ||
|
|
eb152022a0 | ||
|
|
c449ef2e1f | ||
|
|
28a5b702f4 | ||
|
|
8123e334e9 | ||
|
|
66d992d883 | ||
|
|
ee06ef9dd3 | ||
|
|
db9d5f0fa4 | ||
|
|
921f002a6d | ||
|
|
7391cf01a7 | ||
|
|
48d81a796e | ||
|
|
2b7a8eb8f5 | ||
|
|
46e2dd7c32 | ||
|
|
812781cd11 | ||
|
|
1b0f42f8ad | ||
|
|
1b8c094f39 | ||
|
|
c85f77de70 | ||
|
|
1446b543ae | ||
|
|
7c7ca3c6aa | ||
|
|
cb2fa5eab9 | ||
|
|
174d61a56e | ||
|
|
b714af0405 | ||
|
|
6eb97c70b7 | ||
|
|
c94f80502e | ||
|
|
810aca9e68 | ||
|
|
ace0f7f259 | ||
|
|
17571298f3 | ||
|
|
06a7c415a9 | ||
|
|
4062d787da | ||
|
|
0b8aa909a3 | ||
|
|
9ff91d4c6f | ||
|
|
91163f167e | ||
|
|
31fe1cc62b | ||
|
|
5eb82755db | ||
|
|
7fc2eee55c | ||
|
|
b3a8eed49e | ||
|
|
2d292e69a1 | ||
|
|
545a37b306 | ||
|
|
89059f94c0 | ||
|
|
772b302187 | ||
|
|
585027aa96 | ||
|
|
e23194a1fa | ||
|
|
4fbe3cda33 | ||
|
|
8bcb2ae1b2 | ||
|
|
0f0c2d9c02 | ||
|
|
38cbb40e90 | ||
|
|
5d55647a3c | ||
|
|
c27e76aa2a | ||
|
|
c93eca4fe4 | ||
|
|
ce8c1886a5 | ||
|
|
3beb383236 | ||
|
|
823f832630 | ||
|
|
684723488d | ||
|
|
185fba4189 | ||
|
|
1b85b55059 | ||
|
|
bec84fa00a | ||
|
|
15b8a57096 | ||
|
|
85642f887c | ||
|
|
ab73c9bc4e | ||
|
|
dbefae52b0 | ||
|
|
a3ebdd0aeb | ||
|
|
11b2d33523 | ||
|
|
32a682b88f | ||
|
|
c23400278a | ||
|
|
cf36410e30 | ||
|
|
3b4b3b75a6 | ||
|
|
db560e9439 | ||
|
|
38f6467c06 | ||
|
|
c1b7267a2f | ||
|
|
4b8470f3ae | ||
|
|
b0c50fbd4d | ||
|
|
2775173d4d | ||
|
|
e3e5d4ad7a | ||
|
|
af26ac56bf | ||
|
|
7f00523e2e | ||
|
|
a5a50eaafe | ||
|
|
d35a3ac375 | ||
|
|
db6fcce78f | ||
|
|
e939c4072c | ||
|
|
b88677454b | ||
|
|
0d9376da70 | ||
|
|
47b4cf22cd | ||
|
|
87d84b7cb8 | ||
|
|
a25325e9be | ||
|
|
75c6695932 | ||
|
|
cf08675702 | ||
|
|
c59d3426b8 | ||
|
|
4d5105c8f1 | ||
|
|
6839382480 | ||
|
|
2047f88334 | ||
|
|
f43fafc680 | ||
|
|
0a50e6c933 | ||
|
|
d97a25fbdd | ||
|
|
288831854b | ||
|
|
0ed7ba3f5e | ||
|
|
07fd82b411 | ||
|
|
83f0a7b6f8 | ||
|
|
45e1ae2896 | ||
|
|
d457addfc3 | ||
|
|
0ae39f1957 | ||
|
|
48e325df3c | ||
|
|
f449f98dec | ||
|
|
44f7055a04 | ||
|
|
73cb4392ab | ||
|
|
90355c78ed | ||
|
|
3b3a7cc8ba | ||
|
|
d16722481f | ||
|
|
8f98573658 | ||
|
|
c6f5d819af | ||
|
|
ffb9fcc5a2 | ||
|
|
b3be007afa | ||
|
|
f3d3ab5a69 | ||
|
|
10a08a372f | ||
|
|
bb7bb37fe2 | ||
|
|
f2d7998a96 | ||
|
|
33f86ada92 | ||
|
|
1c821373ad | ||
|
|
50ff5ed790 | ||
|
|
eb550ed23b | ||
|
|
69fe7585a2 | ||
|
|
21c2a68aa0 | ||
|
|
86ffc48129 | ||
|
|
2ce9a0e2fe | ||
|
|
3b8b290a45 | ||
|
|
94e72b16e7 | ||
|
|
c5d3ce684a | ||
|
|
2215567d7a | ||
|
|
a2779556b4 | ||
|
|
03b23994f1 | ||
|
|
165d136614 | ||
|
|
93ef24e6fe | ||
|
|
b7d89ff822 | ||
|
|
c1a437add7 | ||
|
|
9e406656c7 | ||
|
|
0d38e3b663 | ||
|
|
8185070841 | ||
|
|
52b75c5fa0 | ||
|
|
7b18df138d | ||
|
|
48a2a8dabd | ||
|
|
ddea94daea | ||
|
|
9a986f374e | ||
|
|
3d35b6b36d | ||
|
|
f332bb3bca | ||
|
|
9bd69bf49f | ||
|
|
c4eef48025 | ||
|
|
77e4679aec | ||
|
|
44e84bb22a | ||
|
|
e97bf88bad | ||
|
|
f1c9f649da | ||
|
|
9036c18170 | ||
|
|
f0afec709e | ||
|
|
e250ffb319 | ||
|
|
24d6a93f44 | ||
|
|
c635976cd7 | ||
|
|
fb498eb925 | ||
|
|
14673d0c49 | ||
|
|
9228842fa7 | ||
|
|
036d94112d | ||
|
|
c1c4040d75 | ||
|
|
872cc430c0 | ||
|
|
b8adf0090e | ||
|
|
2596273fce | ||
|
|
3f829d11ff | ||
|
|
36f74e46b4 | ||
|
|
776364f395 | ||
|
|
2887f40f76 | ||
|
|
9b09fc376e | ||
|
|
a7fb00e887 | ||
|
|
c31dc7aa0c | ||
|
|
9d347f8742 | ||
|
|
1f6781f0ee | ||
|
|
4ab4efd3a6 | ||
|
|
7901d1e3ad | ||
|
|
bcc9137a10 | ||
|
|
82c5edb31c | ||
|
|
5e6fabefd7 | ||
|
|
27988c5e66 | ||
|
|
9775aea1ab | ||
|
|
2fe5210a33 | ||
|
|
93de8d8038 | ||
|
|
441a089aa4 | ||
|
|
1203348302 | ||
|
|
0c928da96d | ||
|
|
3ba37e1e3f | ||
|
|
433ecdfc9d | ||
|
|
bdae4a59c3 | ||
|
|
a919a373da | ||
|
|
66b54af8ea | ||
|
|
87db8b637e | ||
|
|
632ee5a540 | ||
|
|
10b4802869 | ||
|
|
5fcd1fef1c | ||
|
|
d351384fdc | ||
|
|
952e83e0ca | ||
|
|
d6ce75b4d6 | ||
|
|
5344b2e73b | ||
|
|
de7a214c17 | ||
|
|
dd72577759 | ||
|
|
6709933d78 | ||
|
|
dc265feb63 | ||
|
|
a867f42597 | ||
|
|
128e46f91b | ||
|
|
20a1cba286 | ||
|
|
741841d863 | ||
|
|
a64727ba7d | ||
|
|
3de023b6c6 | ||
|
|
6eac6b7254 | ||
|
|
8eb86ab78d | ||
|
|
2220467fcf | ||
|
|
a28b18fa16 | ||
|
|
036ff17916 | ||
|
|
1f62f2253c | ||
|
|
c7a4e11bf1 | ||
|
|
209caeedee | ||
|
|
ac0b7d82d8 | ||
|
|
765992396f | ||
|
|
07eb850608 | ||
|
|
1a8e7d9fbb | ||
|
|
239fdf0b87 | ||
|
|
eb78e94300 | ||
|
|
80b4c698c2 | ||
|
|
b0b29d8013 | ||
|
|
2ab42855cb | ||
|
|
a4ed587f61 | ||
|
|
1578322b06 | ||
|
|
4686236091 | ||
|
|
be7e339d8a | ||
|
|
a64a6f36a0 | ||
|
|
6525a15919 | ||
|
|
4d5fcfb971 | ||
|
|
3ad3168125 | ||
|
|
809f489662 | ||
|
|
2cb1fd6a10 | ||
|
|
83b0bd3095 | ||
|
|
e4ed4e7f4f | ||
|
|
e9406c09a3 | ||
|
|
47abdbd3d5 | ||
|
|
6d4166df61 | ||
|
|
8de9b7a631 | ||
|
|
6655e06ec8 | ||
|
|
d2cf970a41 | ||
|
|
e6f43dd0c6 | ||
|
|
a3b932b3f9 | ||
|
|
264a103610 | ||
|
|
34dabe496f | ||
|
|
87574de8ed | ||
|
|
78e83d8761 | ||
|
|
a135dd50c6 | ||
|
|
558258a301 | ||
|
|
6825c5db72 | ||
|
|
f740485a5a | ||
|
|
9ff7a0bc98 | ||
|
|
197a6acb30 | ||
|
|
d3c432244c | ||
|
|
27bcc8f583 | ||
|
|
95bc36a149 | ||
|
|
4d05a6319d | ||
|
|
95b9a477b6 | ||
|
|
d63ec6f20d | ||
|
|
b9aeac0a64 | ||
|
|
253bad7993 | ||
|
|
900871ca8d | ||
|
|
62ba135228 | ||
|
|
a975008ae7 | ||
|
|
2650584ac4 | ||
|
|
5caf6235cf | ||
|
|
3aa26a794e | ||
|
|
a40814cc9d | ||
|
|
4e5170d4a5 | ||
|
|
280e20b1d3 | ||
|
|
e20bf69ac5 | ||
|
|
b0abcfde9d | ||
|
|
5299142286 | ||
|
|
2341ee5142 | ||
|
|
bdb9387a74 | ||
|
|
903b6001e7 | ||
|
|
0de95730ad | ||
|
|
b54862406e | ||
|
|
070b86a870 | ||
|
|
0e5c0ee045 | ||
|
|
cda8c41ef3 | ||
|
|
4a01eb09d8 | ||
|
|
50b040ef83 | ||
|
|
88a3ccab9f | ||
|
|
7fa712e00c | ||
|
|
8bbde91f62 | ||
|
|
3db219477a | ||
|
|
41e112360f | ||
|
|
3020a4765d | ||
|
|
94bf4d2c22 | ||
|
|
1308e8ebcf | ||
|
|
e81569bc70 | ||
|
|
dd3d4f7295 | ||
|
|
1445fea582 | ||
|
|
b5e2238483 | ||
|
|
ab4a4ab25e | ||
|
|
d79b867d55 | ||
|
|
614790dc14 | ||
|
|
e500c9118a | ||
|
|
56d6abdb3d | ||
|
|
c0620c8a00 | ||
|
|
b573072300 | ||
|
|
d2e125186f | ||
|
|
55cb2170cd | ||
|
|
720a32ede4 | ||
|
|
679f0794f8 | ||
|
|
a5279b2c05 | ||
|
|
a26bf10de3 | ||
|
|
50055880f9 | ||
|
|
1383055b17 | ||
|
|
0a3bcb57f6 | ||
|
|
c15e37edad | ||
|
|
2fdb45f577 | ||
|
|
3065e70630 | ||
|
|
ae23c46ce2 | ||
|
|
b7d7af4fa2 | ||
|
|
2f73e42d87 | ||
|
|
526c464504 | ||
|
|
0d768b9713 | ||
|
|
2349efa61b | ||
|
|
bc48cc1edb | ||
|
|
5b113f3ee3 | ||
|
|
dd70d19267 | ||
|
|
5dadff3de5 | ||
|
|
3a1380120d | ||
|
|
834b782a9c | ||
|
|
569c20f104 | ||
|
|
1026ca5888 | ||
|
|
d923e652f2 | ||
|
|
0d34c2136e | ||
|
|
697f9e305d | ||
|
|
b08dfb8273 | ||
|
|
f88350b611 | ||
|
|
c998985c74 | ||
|
|
94ae3984b0 | ||
|
|
1df662c1b0 | ||
|
|
9fda4f4248 | ||
|
|
97738d1ae9 | ||
|
|
bb5e0df79a | ||
|
|
fc977d56c9 | ||
|
|
c0fc0fa0c4 | ||
|
|
dc251a7d8d | ||
|
|
06aed3d171 | ||
|
|
09ac9faf59 | ||
|
|
035918ef2f | ||
|
|
459875796b | ||
|
|
3ba1532cfb | ||
|
|
3ea4acb9b9 | ||
|
|
719ba918dd | ||
|
|
f366cb20fe | ||
|
|
fe8def3303 | ||
|
|
dcfad3af49 | ||
|
|
370cdeb628 | ||
|
|
bed17847bd | ||
|
|
d0b432ab38 | ||
|
|
5e83b64dae | ||
|
|
85e481b66e | ||
|
|
fcdb663dde | ||
|
|
045cff28fe | ||
|
|
0085c648f6 | ||
|
|
c93ddac9aa | ||
|
|
ec4a350620 | ||
|
|
c4b7e77bbe | ||
|
|
610fd47510 | ||
|
|
ec54c34b9e | ||
|
|
e4ae77c7bb | ||
|
|
956b4beec1 | ||
|
|
6a004ed19f | ||
|
|
c3701df16c | ||
|
|
a342bbadc8 | ||
|
|
69fdb57edd | ||
|
|
bba515afe5 | ||
|
|
e7297581fc | ||
|
|
dca2b15df4 | ||
|
|
8ea8305199 |
23
.cvsignore → .gitignore
vendored
23
.cvsignore → .gitignore
vendored
@@ -1,5 +1,8 @@
|
||||
*.o
|
||||
*.a
|
||||
tcc_g
|
||||
tcc
|
||||
/*-tcc
|
||||
tc2.c
|
||||
doc
|
||||
tc3s.c
|
||||
@@ -7,8 +10,12 @@ p3.c
|
||||
tc1.c
|
||||
error.c
|
||||
i386-gen1.c
|
||||
test.out1
|
||||
test.out1b
|
||||
test.out2
|
||||
test.out2b
|
||||
test.out3
|
||||
test.out3b
|
||||
web.sh
|
||||
memdebug.c
|
||||
bench
|
||||
@@ -28,10 +35,24 @@ p.c
|
||||
p2.c
|
||||
tcctest[1234]
|
||||
test[1234].out
|
||||
tests/tcclib.h
|
||||
tests/tcctest.gcc
|
||||
tests/weaktest.*.o.txt
|
||||
tests2/fred.txt
|
||||
.gdb_history
|
||||
tcc.1
|
||||
tcc.pod
|
||||
config.h
|
||||
config.mak
|
||||
config.texi
|
||||
tests
|
||||
tags
|
||||
.DS_Store
|
||||
*.swp
|
||||
lib/x86_64
|
||||
lib/i386
|
||||
lib/x86_64-win32
|
||||
lib/i386-win32
|
||||
tcc-doc.info
|
||||
conftest*
|
||||
tiny_libmaker
|
||||
*.dSYM
|
||||
28
Changelog
28
Changelog
@@ -1,3 +1,31 @@
|
||||
version 0.9.26:
|
||||
|
||||
User interface:
|
||||
- -MD/-MF (automatically generate dependencies for make)
|
||||
- -pthread option (same as -D_REENTRANT -lpthread) (Henry Kroll III)
|
||||
- -m32/-m64 to re-exec cross compiler (Henry Kroll III)
|
||||
- -Wl, Mimic all GNU -option forms supported by ld (Kirill Smelkov)
|
||||
- new LIBTCCAPI tcc_set_options() (grischka)
|
||||
|
||||
Platforms:
|
||||
- Many improvements for x86-64 target (Shinichiro Hamaji, Michael Matz, grischka)
|
||||
- x86-64 assembler (Frederic Feret)
|
||||
- Many improvements for ARM target (Daniel Glöckner, Thomas Preud'homme)
|
||||
- Support WinCE PE ARM (Timo VJ Lahde)
|
||||
- Support ARM hardfloat calling convention (Thomas Preud'homme)
|
||||
- Support SELinux (Security-Enhanced Linux) (Henry Kroll III)
|
||||
- Support Debian GNU/kFreeBSD kernels (Pierre Chifflier)
|
||||
- Support GNU/Hurd kernels (Thomas Preud'homme)
|
||||
- Support OSX (tcc -run only) (Milutin Jovanovic)
|
||||
- Support multiarch configuration (Thomas Preud'homme)
|
||||
- Support out-of-tree build (Akim Demaille)
|
||||
|
||||
Features:
|
||||
- C99 variable length arrays (Thomas Preud'homme & Joe Soroka)
|
||||
- Asm labels for variables and functions (Thomas Preud'homme)
|
||||
- STT_GNU_IFUNC (Indirect functions as externals) (Thomas Preud'homme)
|
||||
- More tests (tests2) (Milutin Jovanovic)
|
||||
|
||||
version 0.9.25:
|
||||
|
||||
- first support for x86-64 target (Shinichiro Hamaji)
|
||||
|
||||
425
Makefile
425
Makefile
@@ -4,29 +4,36 @@
|
||||
|
||||
TOP ?= .
|
||||
include $(TOP)/config.mak
|
||||
VPATH = $(top_srcdir)
|
||||
|
||||
CFLAGS+=-g -Wall
|
||||
CFLAGS_P=$(CFLAGS) -pg -static -DCONFIG_TCC_STATIC
|
||||
LIBS_P=
|
||||
CPPFLAGS = -I$(TOP) # for config.h
|
||||
|
||||
ifneq ($(GCC_MAJOR),2)
|
||||
ifeq (-$(findstring gcc,$(CC))-,-gcc-)
|
||||
ifeq (-$(findstring $(GCC_MAJOR),01)-,--)
|
||||
CFLAGS+=-fno-strict-aliasing
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),i386)
|
||||
CFLAGS+=-mpreferred-stack-boundary=2
|
||||
ifeq ($(GCC_MAJOR),2)
|
||||
CFLAGS+=-m386 -malign-functions=0
|
||||
ifeq (-$(findstring $(GCC_MAJOR),23)-,--)
|
||||
CFLAGS+=-Wno-pointer-sign -Wno-sign-compare
|
||||
ifeq (-$(GCC_MAJOR)-$(findstring $(GCC_MINOR),56789)-,-4--)
|
||||
CFLAGS+=-D_FORTIFY_SOURCE=0
|
||||
else
|
||||
CFLAGS+=-march=i386 -falign-functions=0
|
||||
ifneq ($(GCC_MAJOR),3)
|
||||
CFLAGS+=-Wno-pointer-sign -Wno-sign-compare -D_FORTIFY_SOURCE=0
|
||||
CFLAGS+=-Wno-unused-result
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
else # not GCC
|
||||
ifeq (-$(findstring clang,$(CC))-,-clang-)
|
||||
# make clang accept gnuisms in libtcc1.c
|
||||
CFLAGS+=-fheinous-gnu-extensions
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),x86-64)
|
||||
CFLAGS+=-Wno-pointer-sign
|
||||
CPPFLAGS_P=$(CPPFLAGS) -DCONFIG_TCC_STATIC
|
||||
CFLAGS_P=$(CFLAGS) -pg -static
|
||||
LIBS_P=
|
||||
LDFLAGS_P=$(LDFLAGS)
|
||||
|
||||
ifdef CONFIG_WIN64
|
||||
CONFIG_WIN32=yes
|
||||
endif
|
||||
|
||||
ifndef CONFIG_WIN32
|
||||
@@ -36,209 +43,259 @@ LIBS+=-ldl
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WIN32
|
||||
NATIVE_TARGET=-DTCC_TARGET_PE
|
||||
LIBTCC1=libtcc1.a
|
||||
else
|
||||
ifeq ($(ARCH),i386)
|
||||
NATIVE_TARGET=-DTCC_TARGET_I386
|
||||
LIBTCC1=libtcc1.a
|
||||
BCHECK_O=bcheck.o
|
||||
else
|
||||
ifeq ($(ARCH),arm)
|
||||
NATIVE_TARGET=-DTCC_TARGET_ARM
|
||||
NATIVE_TARGET+=$(if $(wildcard /lib/ld-linux.so.3),-DTCC_ARM_EABI)
|
||||
NATIVE_TARGET+=$(if $(shell grep -l "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo),-DTCC_ARM_VFP)
|
||||
else
|
||||
ifeq ($(ARCH),x86-64)
|
||||
NATIVE_TARGET=-DTCC_TARGET_X86_64
|
||||
LIBTCC1=libtcc1.a
|
||||
endif
|
||||
endif
|
||||
# make libtcc as static or dynamic library?
|
||||
ifdef DISABLE_STATIC
|
||||
LIBTCC=libtcc.so.1.0
|
||||
LINK_LIBTCC=-Wl,-rpath,"$(libdir)"
|
||||
ifdef DISABLE_RPATH
|
||||
LINK_LIBTCC=
|
||||
endif
|
||||
else
|
||||
LIBTCC=libtcc.a
|
||||
LINK_LIBTCC=
|
||||
endif
|
||||
|
||||
ifneq ($(wildcard /lib/ld-uClibc.so.0),)
|
||||
NATIVE_TARGET+=-DTCC_UCLIBC
|
||||
BCHECK_O=
|
||||
CONFIG_$(ARCH) = yes
|
||||
NATIVE_DEFINES_$(CONFIG_i386) += -DTCC_TARGET_I386
|
||||
NATIVE_DEFINES_$(CONFIG_x86-64) += -DTCC_TARGET_X86_64
|
||||
NATIVE_DEFINES_$(CONFIG_WIN32) += -DTCC_TARGET_PE
|
||||
NATIVE_DEFINES_$(CONFIG_uClibc) += -DTCC_UCLIBC
|
||||
NATIVE_DEFINES_$(CONFIG_arm) += -DTCC_TARGET_ARM -DWITHOUT_LIBTCC
|
||||
NATIVE_DEFINES_$(CONFIG_arm_eabihf) += -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT
|
||||
NATIVE_DEFINES_$(CONFIG_arm_eabi) += -DTCC_ARM_EABI
|
||||
NATIVE_DEFINES_$(CONFIG_arm_vfp) += -DTCC_ARM_VFP
|
||||
NATIVE_DEFINES += $(NATIVE_DEFINES_yes)
|
||||
|
||||
ifeq ($(TOP),.)
|
||||
|
||||
PROGS=tcc$(EXESUF)
|
||||
I386_CROSS = i386-tcc$(EXESUF)
|
||||
WIN32_CROSS = i386-win32-tcc$(EXESUF)
|
||||
WIN64_CROSS = x86_64-win32-tcc$(EXESUF)
|
||||
WINCE_CROSS = arm-win32-tcc$(EXESUF)
|
||||
X64_CROSS = x86_64-tcc$(EXESUF)
|
||||
ARM_FPA_CROSS = arm-fpa-tcc$(EXESUF)
|
||||
ARM_FPA_LD_CROSS = arm-fpa-ld-tcc$(EXESUF)
|
||||
ARM_VFP_CROSS = arm-vfp-tcc$(EXESUF)
|
||||
ARM_EABI_CROSS = arm-eabi-tcc$(EXESUF)
|
||||
ARM_CROSS = $(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CROSS)
|
||||
C67_CROSS = c67-tcc$(EXESUF)
|
||||
|
||||
CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c
|
||||
CORE_FILES += tcc.h config.h libtcc.h tcctok.h
|
||||
I386_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h
|
||||
WIN32_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h tccpe.c
|
||||
WIN64_FILES = $(CORE_FILES) x86_64-gen.c i386-asm.c x86_64-asm.h tccpe.c
|
||||
WINCE_FILES = $(CORE_FILES) arm-gen.c tccpe.c
|
||||
X86_64_FILES = $(CORE_FILES) x86_64-gen.c i386-asm.c x86_64-asm.h
|
||||
ARM_FILES = $(CORE_FILES) arm-gen.c
|
||||
C67_FILES = $(CORE_FILES) c67-gen.c tcccoff.c
|
||||
|
||||
ifdef CONFIG_WIN64
|
||||
PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF)
|
||||
NATIVE_FILES=$(WIN64_FILES)
|
||||
PROGS_CROSS=$(WIN32_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(C67_CROSS)
|
||||
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a
|
||||
LIBTCC1=libtcc1.a
|
||||
else ifdef CONFIG_WIN32
|
||||
PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF)
|
||||
NATIVE_FILES=$(WIN32_FILES)
|
||||
PROGS_CROSS=$(WIN64_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(C67_CROSS)
|
||||
LIBTCC1_CROSS=lib/x86_64-win32/libtcc1.a
|
||||
LIBTCC1=libtcc1.a
|
||||
else ifeq ($(ARCH),i386)
|
||||
NATIVE_FILES=$(I386_FILES)
|
||||
PROGS_CROSS=$(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS)
|
||||
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a
|
||||
LIBTCC1=libtcc1.a
|
||||
else ifeq ($(ARCH),x86-64)
|
||||
NATIVE_FILES=$(X86_64_FILES)
|
||||
PROGS_CROSS=$(I386_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS)
|
||||
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a lib/i386/libtcc1.a
|
||||
LIBTCC1=libtcc1.a
|
||||
else ifeq ($(ARCH),arm)
|
||||
NATIVE_FILES=$(ARM_FILES)
|
||||
PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(C67_CROSS)
|
||||
endif
|
||||
|
||||
ifeq ($(TARGETOS),Darwin)
|
||||
PROGS+=tiny_libmaker$(EXESUF)
|
||||
endif
|
||||
|
||||
ifdef CONFIG_USE_LIBGCC
|
||||
LIBTCC1=
|
||||
endif
|
||||
|
||||
ifeq ($(TOP),.)
|
||||
|
||||
PROGS=tcc$(EXESUF)
|
||||
|
||||
I386_CROSS = i386-tcc$(EXESUF)
|
||||
WIN32_CROSS = i386-win32-tcc$(EXESUF)
|
||||
X64_CROSS = x86_64-tcc$(EXESUF)
|
||||
ARM_CROSS = arm-tcc-fpa$(EXESUF) arm-tcc-fpa-ld$(EXESUF) \
|
||||
arm-tcc-vfp$(EXESUF) arm-tcc-vfp-eabi$(EXESUF)
|
||||
C67_CROSS = c67-tcc$(EXESUF)
|
||||
|
||||
CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c \
|
||||
tcc.h config.h libtcc.h tcctok.h
|
||||
I386_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h
|
||||
WIN32_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h tccpe.c
|
||||
X86_64_FILES = $(CORE_FILES) x86_64-gen.c
|
||||
ARM_FILES = $(CORE_FILES) arm-gen.c
|
||||
C67_FILES = $(CORE_FILES) c67-gen.c tcccoff.c
|
||||
|
||||
ifdef CONFIG_WIN32
|
||||
PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF)
|
||||
NATIVE_FILES=$(WIN32_FILES)
|
||||
PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(C67_CROSS)
|
||||
else
|
||||
ifeq ($(ARCH),i386)
|
||||
NATIVE_FILES=$(I386_FILES)
|
||||
PROGS_CROSS=$(X64_CROSS) $(WIN32_CROSS) $(ARM_CROSS) $(C67_CROSS)
|
||||
else
|
||||
ifeq ($(ARCH),x86-64)
|
||||
NATIVE_FILES=$(X86_64_FILES)
|
||||
PROGS_CROSS=$(I386_CROSS) $(WIN32_CROSS) $(ARM_CROSS) $(C67_CROSS)
|
||||
else
|
||||
ifeq ($(ARCH),arm)
|
||||
NATIVE_FILES=$(ARM_FILES)
|
||||
PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(C67_CROSS)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
TCCLIBS = $(LIBTCC1) $(LIBTCC)
|
||||
TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
|
||||
|
||||
ifdef CONFIG_CROSS
|
||||
PROGS+=$(PROGS_CROSS)
|
||||
TCCLIBS+=$(LIBTCC1_CROSS)
|
||||
endif
|
||||
|
||||
all: $(PROGS) $(LIBTCC1) $(BCHECK_O) libtcc.a tcc-doc.html tcc.1 libtcc_test$(EXESUF)
|
||||
all: $(PROGS) $(TCCLIBS) $(TCCDOCS)
|
||||
|
||||
# Host Tiny C Compiler
|
||||
tcc$(EXESUF): $(NATIVE_FILES)
|
||||
$(CC) -o $@ $< $(NATIVE_TARGET) $(CFLAGS) $(LIBS)
|
||||
tcc$(EXESUF): tcc.o $(LIBTCC)
|
||||
$(CC) -o $@ $^ $(LIBS) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LINK_LIBTCC)
|
||||
|
||||
# Cross Tiny C Compilers
|
||||
i386-tcc$(EXESUF): $(I386_FILES)
|
||||
$(CC) -o $@ $< -DTCC_TARGET_I386 $(CFLAGS) $(LIBS)
|
||||
|
||||
i386-win32-tcc$(EXESUF): $(WIN32_FILES)
|
||||
$(CC) -o $@ $< -DTCC_TARGET_PE $(CFLAGS) $(LIBS)
|
||||
|
||||
x86_64-tcc$(EXESUF): $(X86_64_FILES)
|
||||
$(CC) -o $@ $< -DTCC_TARGET_X86_64 $(CFLAGS) $(LIBS)
|
||||
|
||||
c67-tcc$(EXESUF): $(C67_FILES)
|
||||
$(CC) -o $@ $< -DTCC_TARGET_C67 $(CFLAGS) $(LIBS)
|
||||
|
||||
arm-tcc-fpa$(EXESUF): $(ARM_FILES)
|
||||
$(CC) -o $@ $< -DTCC_TARGET_ARM $(CFLAGS) $(LIBS)
|
||||
|
||||
arm-tcc-fpa-ld$(EXESUF): $(ARM_FILES)
|
||||
$(CC) -o $@ $< -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12 $(CFLAGS) $(LIBS)
|
||||
|
||||
arm-tcc-vfp$(EXESUF): $(ARM_FILES)
|
||||
$(CC) -o $@ $< -DTCC_TARGET_ARM -DTCC_ARM_VFP $(CFLAGS) $(LIBS)
|
||||
|
||||
arm-tcc-vfp-eabi$(EXESUF): $(ARM_FILES)
|
||||
$(CC) -o $@ $< -DTCC_TARGET_ARM -DTCC_ARM_EABI $(CFLAGS) $(LIBS)
|
||||
|
||||
# libtcc generation and test
|
||||
libtcc.o: $(NATIVE_FILES)
|
||||
$(CC) -o $@ -c libtcc.c $(NATIVE_TARGET) $(CFLAGS)
|
||||
|
||||
libtcc.a: libtcc.o
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
libtcc_test$(EXESUF): tests/libtcc_test.c libtcc.a
|
||||
$(CC) -o $@ $^ -I. $(CFLAGS) $(LIBS)
|
||||
|
||||
libtest: libtcc_test$(EXESUF) $(LIBTCC1)
|
||||
./libtcc_test$(EXESUF) lib_path=.
|
||||
%-tcc$(EXESUF): tcc.c
|
||||
$(CC) -o $@ $< -DONE_SOURCE $(DEFINES) $(CPPFLAGS) $(CFLAGS) $(LIBS) $(LDFLAGS)
|
||||
|
||||
# profiling version
|
||||
tcc_p$(EXESUF): $(NATIVE_FILES)
|
||||
$(CC) -o $@ $< $(NATIVE_TARGET) $(CFLAGS_P) $(LIBS_P)
|
||||
$(CC) -o $@ $< -DONE_SOURCE $(NATIVE_DEFINES) $(CPPFLAGS_P) $(CFLAGS_P) $(LIBS_P) $(LDFLAGS_P)
|
||||
|
||||
$(I386_CROSS): DEFINES = -DTCC_TARGET_I386 \
|
||||
-DCONFIG_TCCDIR="\"$(tccdir)/i386\""
|
||||
$(X64_CROSS): DEFINES = -DTCC_TARGET_X86_64
|
||||
$(WIN32_CROSS): DEFINES = -DTCC_TARGET_I386 -DTCC_TARGET_PE \
|
||||
-DCONFIG_TCCDIR="\"$(tccdir)/win32\"" \
|
||||
-DCONFIG_TCC_LIBPATHS="\"{B}/lib/32;{B}/lib\""
|
||||
$(WIN64_CROSS): DEFINES = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE \
|
||||
-DCONFIG_TCCDIR="\"$(tccdir)/win32\"" \
|
||||
-DCONFIG_TCC_LIBPATHS="\"{B}/lib/64;{B}/lib\""
|
||||
$(WINCE_CROSS): DEFINES = -DTCC_TARGET_PE
|
||||
$(C67_CROSS): DEFINES = -DTCC_TARGET_C67
|
||||
$(ARM_FPA_CROSS): DEFINES = -DTCC_TARGET_ARM
|
||||
$(ARM_FPA_LD_CROSS)$(EXESUF): DEFINES = -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12
|
||||
$(ARM_VFP_CROSS): DEFINES = -DTCC_TARGET_ARM -DTCC_ARM_VFP
|
||||
$(ARM_EABI_CROSS): DEFINES = -DTCC_TARGET_ARM -DTCC_ARM_EABI
|
||||
|
||||
$(I386_CROSS): $(I386_FILES)
|
||||
$(X64_CROSS): $(X86_64_FILES)
|
||||
$(WIN32_CROSS): $(WIN32_FILES)
|
||||
$(WIN64_CROSS): $(WIN64_FILES)
|
||||
$(WINCE_CROSS): $(WINCE_FILES)
|
||||
$(C67_CROSS): $(C67_FILES)
|
||||
$(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CROSS): $(ARM_FILES)
|
||||
|
||||
# libtcc generation and test
|
||||
ifndef ONE_SOURCE
|
||||
LIBTCC_OBJ = $(filter-out tcc.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES))))
|
||||
LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES),$(NATIVE_FILES))
|
||||
else
|
||||
LIBTCC_OBJ = libtcc.o
|
||||
LIBTCC_INC = $(NATIVE_FILES)
|
||||
libtcc.o : NATIVE_DEFINES += -DONE_SOURCE
|
||||
endif
|
||||
|
||||
$(LIBTCC_OBJ) tcc.o : %.o : %.c $(LIBTCC_INC)
|
||||
$(CC) -o $@ -c $< $(NATIVE_DEFINES) $(CPPFLAGS) $(CFLAGS)
|
||||
|
||||
libtcc.a: $(LIBTCC_OBJ)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
libtcc.so.1.0: $(LIBTCC_OBJ)
|
||||
$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDFLAGS)
|
||||
|
||||
libtcc.so.1.0: CFLAGS+=-fPIC
|
||||
|
||||
# windows utilities
|
||||
tiny_impdef$(EXESUF): win32/tools/tiny_impdef.c
|
||||
$(CC) -o $@ $< $(CFLAGS)
|
||||
$(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
|
||||
tiny_libmaker$(EXESUF): win32/tools/tiny_libmaker.c
|
||||
$(CC) -o $@ $< $(CFLAGS)
|
||||
$(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
# TinyCC runtime libraries
|
||||
LIBTCC1_OBJS=libtcc1.o
|
||||
LIBTCC1_CC=$(CC)
|
||||
VPATH+=lib
|
||||
ifdef CONFIG_WIN32
|
||||
# for windows, we must use TCC because we generate ELF objects
|
||||
LIBTCC1_OBJS+=crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
|
||||
LIBTCC1_CC=./tcc.exe -Bwin32 -DTCC_TARGET_PE
|
||||
VPATH+=win32/lib
|
||||
endif
|
||||
ifeq ($(ARCH),i386)
|
||||
LIBTCC1_OBJS+=alloca86.o alloca86-bt.o
|
||||
endif
|
||||
libtcc1.a : FORCE
|
||||
$(MAKE) -C lib native
|
||||
lib/%/libtcc1.a : FORCE $(PROGS_CROSS)
|
||||
$(MAKE) -C lib cross TARGET=$*
|
||||
|
||||
%.o: %.c
|
||||
$(LIBTCC1_CC) -o $@ -c $< -O2 -Wall
|
||||
|
||||
%.o: %.S
|
||||
$(LIBTCC1_CC) -o $@ -c $<
|
||||
|
||||
libtcc1.a: $(LIBTCC1_OBJS)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
bcheck.o: bcheck.c
|
||||
$(CC) -o $@ -c $< -O2 -Wall
|
||||
FORCE:
|
||||
|
||||
# install
|
||||
TCC_INCLUDES = stdarg.h stddef.h stdbool.h float.h varargs.h tcclib.h
|
||||
INSTALL=install
|
||||
ifdef STRIP_BINARIES
|
||||
INSTALLBIN=$(INSTALL) -s
|
||||
else
|
||||
INSTALLBIN=$(INSTALL)
|
||||
endif
|
||||
|
||||
ifndef CONFIG_WIN32
|
||||
install: $(PROGS) $(LIBTCC1) $(BCHECK_O) libtcc.a tcc.1 tcc-doc.html
|
||||
install: $(PROGS) $(TCCLIBS) $(TCCDOCS)
|
||||
mkdir -p "$(bindir)"
|
||||
$(INSTALL) -s -m755 $(PROGS) "$(bindir)"
|
||||
ifeq ($(CC),tcc)
|
||||
$(INSTALL) -m755 $(PROGS) "$(bindir)"
|
||||
else
|
||||
$(INSTALLBIN) -m755 $(PROGS) "$(bindir)"
|
||||
endif
|
||||
mkdir -p "$(mandir)/man1"
|
||||
$(INSTALL) tcc.1 "$(mandir)/man1"
|
||||
-$(INSTALL) tcc.1 "$(mandir)/man1"
|
||||
mkdir -p "$(infodir)"
|
||||
-$(INSTALL) tcc-doc.info "$(infodir)"
|
||||
mkdir -p "$(tccdir)"
|
||||
mkdir -p "$(tccdir)/include"
|
||||
ifneq ($(LIBTCC1),)
|
||||
$(INSTALL) -m644 $(LIBTCC1) "$(tccdir)"
|
||||
endif
|
||||
ifneq ($(BCHECK_O),)
|
||||
$(INSTALL) -m644 $(BCHECK_O) "$(tccdir)"
|
||||
endif
|
||||
$(INSTALL) -m644 $(addprefix include/,$(TCC_INCLUDES)) "$(tccdir)/include"
|
||||
mkdir -p "$(docdir)"
|
||||
$(INSTALL) -m644 tcc-doc.html "$(docdir)"
|
||||
$(INSTALL) -m644 $(addprefix $(top_srcdir)/include/,$(TCC_INCLUDES)) "$(tccdir)/include"
|
||||
mkdir -p "$(libdir)"
|
||||
$(INSTALL) -m644 libtcc.a "$(libdir)"
|
||||
$(INSTALL) -m755 $(LIBTCC) "$(libdir)"
|
||||
ifdef DISABLE_STATIC
|
||||
ln -sf "$(ln_libdir)/libtcc.so.1.0" "$(libdir)/libtcc.so.1"
|
||||
ln -sf "$(ln_libdir)/libtcc.so.1.0" "$(libdir)/libtcc.so"
|
||||
endif
|
||||
mkdir -p "$(includedir)"
|
||||
$(INSTALL) -m644 libtcc.h "$(includedir)"
|
||||
$(INSTALL) -m644 $(top_srcdir)/libtcc.h "$(includedir)"
|
||||
mkdir -p "$(docdir)"
|
||||
-$(INSTALL) -m644 tcc-doc.html "$(docdir)"
|
||||
ifdef CONFIG_CROSS
|
||||
mkdir -p "$(tccdir)/win32/lib/32"
|
||||
mkdir -p "$(tccdir)/win32/lib/64"
|
||||
ifeq ($(ARCH),x86-64)
|
||||
mkdir -p "$(tccdir)/i386"
|
||||
$(INSTALL) -m644 lib/i386/libtcc1.a "$(tccdir)/i386"
|
||||
cp -r "$(tccdir)/include" "$(tccdir)/i386"
|
||||
endif
|
||||
$(INSTALL) -m644 win32/lib/*.def "$(tccdir)/win32/lib"
|
||||
$(INSTALL) -m644 lib/i386-win32/libtcc1.a "$(tccdir)/win32/lib/32"
|
||||
$(INSTALL) -m644 lib/x86_64-win32/libtcc1.a "$(tccdir)/win32/lib/64"
|
||||
cp -r win32/include/. "$(tccdir)/win32/include"
|
||||
cp -r include/. "$(tccdir)/win32/include"
|
||||
endif
|
||||
|
||||
uninstall:
|
||||
rm -fv $(foreach P,$(PROGS),"$(bindir)/$P")
|
||||
rm -fv $(foreach P,$(LIBTCC1) $(BCHECK_O),"$(tccdir)/$P")
|
||||
rm -fv $(foreach P,$(LIBTCC1),"$(tccdir)/$P")
|
||||
rm -fv $(foreach P,$(TCC_INCLUDES),"$(tccdir)/include/$P")
|
||||
rm -fv "$(docdir)/tcc-doc.html" "$(mandir)/man1/tcc.1"
|
||||
rm -fv "$(libdir)/libtcc.a" "$(includedir)/libtcc.h"
|
||||
|
||||
rm -fv "$(docdir)/tcc-doc.html" "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info"
|
||||
rm -fv "$(libdir)/$(LIBTCC)" "$(includedir)/libtcc.h"
|
||||
rm -fv "$(libdir)/libtcc.so*"
|
||||
rm -rf "$(tccdir)/win32"
|
||||
-rmdir $(tccdir)/include
|
||||
ifeq ($(ARCH),x86-64)
|
||||
rm -rf "$(tccdir)/i386"
|
||||
endif
|
||||
else
|
||||
install: $(PROGS) $(LIBTCC1) libtcc.a tcc-doc.html
|
||||
# on windows
|
||||
install: $(PROGS) $(TCCLIBS) $(TCCDOCS)
|
||||
mkdir -p "$(tccdir)"
|
||||
mkdir -p "$(tccdir)/lib"
|
||||
mkdir -p "$(tccdir)/include"
|
||||
mkdir -p "$(tccdir)/examples"
|
||||
mkdir -p "$(tccdir)/doc"
|
||||
mkdir -p "$(tccdir)/libtcc"
|
||||
$(INSTALL) -s -m755 $(PROGS) "$(tccdir)"
|
||||
$(INSTALLBIN) -m755 $(PROGS) "$(tccdir)"
|
||||
$(INSTALL) -m644 $(LIBTCC1) win32/lib/*.def "$(tccdir)/lib"
|
||||
cp -r win32/include/. "$(tccdir)/include"
|
||||
cp -r win32/examples/. "$(tccdir)/examples"
|
||||
# $(INSTALL) -m644 $(addprefix include/,$(TCC_INCLUDES)) "$(tccdir)/include"
|
||||
$(INSTALL) -m644 $(addprefix include/,$(TCC_INCLUDES)) "$(tccdir)/include"
|
||||
$(INSTALL) -m644 tcc-doc.html win32/tcc-win32.txt "$(tccdir)/doc"
|
||||
$(INSTALL) -m644 libtcc.a libtcc.h "$(tccdir)/libtcc"
|
||||
$(INSTALL) -m644 $(LIBTCC) libtcc.h "$(tccdir)/libtcc"
|
||||
ifdef CONFIG_CROSS
|
||||
mkdir -p "$(tccdir)/lib/32"
|
||||
mkdir -p "$(tccdir)/lib/64"
|
||||
-$(INSTALL) -m644 lib/i386-win32/libtcc1.a "$(tccdir)/lib/32"
|
||||
-$(INSTALL) -m644 lib/x86_64-win32/libtcc1.a "$(tccdir)/lib/64"
|
||||
endif
|
||||
|
||||
uninstall:
|
||||
rm -rfv "$(tccdir)/*"
|
||||
endif
|
||||
|
||||
# documentation and man page
|
||||
@@ -246,27 +303,47 @@ tcc-doc.html: tcc-doc.texi
|
||||
-texi2html -monolithic -number $<
|
||||
|
||||
tcc.1: tcc-doc.texi
|
||||
-./texi2pod.pl $< tcc.pod
|
||||
-$(top_srcdir)/texi2pod.pl $< tcc.pod
|
||||
-pod2man --section=1 --center=" " --release=" " tcc.pod > $@
|
||||
|
||||
# tar release (use 'make -k tar' on a checkouted tree)
|
||||
TCC-VERSION=tcc-$(shell cat VERSION)
|
||||
tar:
|
||||
rm -rf /tmp/$(TCC-VERSION)
|
||||
cp -r . /tmp/$(TCC-VERSION)
|
||||
( cd /tmp ; tar zcvf ~/$(TCC-VERSION).tar.gz $(TCC-VERSION) --exclude CVS )
|
||||
rm -rf /tmp/$(TCC-VERSION)
|
||||
tcc-doc.info: tcc-doc.texi
|
||||
-makeinfo $<
|
||||
|
||||
# in tests subdir
|
||||
test clean :
|
||||
export LIBTCC1
|
||||
|
||||
%est:
|
||||
$(MAKE) -C tests $@
|
||||
|
||||
# clean
|
||||
clean: local_clean
|
||||
local_clean:
|
||||
rm -vf $(PROGS) tcc_p$(EXESUF) tcc.pod *~ *.o *.a *.out libtcc_test$(EXESUF)
|
||||
clean:
|
||||
rm -vf $(PROGS) tcc_p$(EXESUF) tcc.pod *~ *.o *.a *.so* *.out *.exe libtcc_test$(EXESUF)
|
||||
$(MAKE) -C tests $@
|
||||
ifneq ($(LIBTCC1),)
|
||||
$(MAKE) -C lib $@
|
||||
endif
|
||||
|
||||
distclean: clean
|
||||
rm -vf config.h config.mak config.texi tcc.1 tcc-doc.html
|
||||
rm -vf config.h config.mak config.texi tcc.1 tcc-doc.info tcc-doc.html
|
||||
|
||||
config.mak:
|
||||
@echo "Please run ./configure."
|
||||
@exit 1
|
||||
|
||||
# create release tarball from *current* git branch (including tcc-doc.html
|
||||
# and converting two files to CRLF)
|
||||
TCC-VERSION := tcc-$(shell cat $(top_srcdir)/VERSION)
|
||||
tar: tcc-doc.html
|
||||
mkdir $(TCC-VERSION)
|
||||
( cd $(TCC-VERSION) && git --git-dir ../.git checkout -f )
|
||||
cp tcc-doc.html $(TCC-VERSION)
|
||||
for f in tcc-win32.txt build-tcc.bat ; do \
|
||||
cat win32/$$f | sed 's,\(.*\),\1\r,g' > $(TCC-VERSION)/win32/$$f ; \
|
||||
done
|
||||
tar cjf $(TCC-VERSION).tar.bz2 $(TCC-VERSION)
|
||||
rm -rf $(TCC-VERSION)
|
||||
git reset
|
||||
|
||||
|
||||
.PHONY: all clean tar distclean install uninstall FORCE
|
||||
|
||||
endif # ifeq ($(TOP),.)
|
||||
|
||||
13
README
13
README
@@ -35,6 +35,16 @@ Documentation:
|
||||
make test
|
||||
make install
|
||||
|
||||
Alternatively, out-of-tree builds are supported: you may use different
|
||||
directories to hold build objects, kept separate from your source tree:
|
||||
|
||||
mkdir _build
|
||||
cd _build
|
||||
../configure
|
||||
make
|
||||
make test
|
||||
make install
|
||||
|
||||
By default, tcc is installed in /usr/local/bin.
|
||||
./configure --help shows configuration options.
|
||||
|
||||
@@ -65,7 +75,8 @@ operations given a list of numbers (benchmark).
|
||||
ex3.c: compute fibonacci numbers (benchmark).
|
||||
|
||||
ex4.c: more complicated: X11 program. Very complicated test in fact
|
||||
because standard headers are being used !
|
||||
because standard headers are being used ! As for ex1.c, can also be launched
|
||||
directly as a script: './ex4.c'.
|
||||
|
||||
ex5.c: 'hello world' with standard glibc headers.
|
||||
|
||||
|
||||
2
TODO
2
TODO
@@ -46,10 +46,8 @@ Missing features:
|
||||
- disable-asm and disable-bcheck options
|
||||
- __builtin_expect()
|
||||
- improve '-E' option.
|
||||
- add '-MD' option
|
||||
- atexit (Nigel Horne)
|
||||
- packed attribute
|
||||
- C99: add variable size arrays (gcc 3.2 testsuite issue)
|
||||
- C99: add complex types (gcc 3.2 testsuite issue)
|
||||
- postfix compound literals (see 20010124-1.c)
|
||||
|
||||
|
||||
158
c67-gen.c
158
c67-gen.c
@@ -18,6 +18,8 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef TARGET_DEFS_ONLY
|
||||
|
||||
//#define ASSEMBLY_LISTING_C67
|
||||
|
||||
/* number of available registers */
|
||||
@@ -85,12 +87,52 @@ enum {
|
||||
TREG_C67_B13,
|
||||
};
|
||||
|
||||
int reg_classes[NB_REGS] = {
|
||||
/* eax */ RC_INT | RC_FLOAT | RC_EAX,
|
||||
// only allow even regs for floats (allow for doubles)
|
||||
/* return registers for function */
|
||||
#define REG_IRET TREG_C67_A4 /* single word int return register */
|
||||
#define REG_LRET TREG_C67_A5 /* second word return register (for long long) */
|
||||
#define REG_FRET TREG_C67_A4 /* float return register */
|
||||
|
||||
/* defined if function parameters must be evaluated in reverse order */
|
||||
//#define INVERT_FUNC_PARAMS
|
||||
|
||||
/* defined if structures are passed as pointers. Otherwise structures
|
||||
are directly pushed on stack. */
|
||||
//#define FUNC_STRUCT_PARAM_AS_PTR
|
||||
|
||||
/* pointer size, in bytes */
|
||||
#define PTR_SIZE 4
|
||||
|
||||
/* long double size and alignment, in bytes */
|
||||
#define LDOUBLE_SIZE 12
|
||||
#define LDOUBLE_ALIGN 4
|
||||
/* maximum alignment (for aligned attribute support) */
|
||||
#define MAX_ALIGN 8
|
||||
|
||||
/******************************************************/
|
||||
/* ELF defines */
|
||||
|
||||
#define EM_TCC_TARGET EM_C60
|
||||
|
||||
/* relocation type for 32 bit data relocation */
|
||||
#define R_DATA_32 R_C60_32
|
||||
#define R_DATA_PTR R_C60_32
|
||||
#define R_JMP_SLOT R_C60_JMP_SLOT
|
||||
#define R_COPY R_C60_COPY
|
||||
|
||||
#define ELF_START_ADDR 0x00000400
|
||||
#define ELF_PAGE_SIZE 0x1000
|
||||
|
||||
/******************************************************/
|
||||
#else /* ! TARGET_DEFS_ONLY */
|
||||
/******************************************************/
|
||||
#include "tcc.h"
|
||||
|
||||
ST_DATA const int reg_classes[NB_REGS] = {
|
||||
/* eax */ RC_INT | RC_FLOAT | RC_EAX,
|
||||
// only allow even regs for floats (allow for doubles)
|
||||
/* ecx */ RC_INT | RC_ECX,
|
||||
/* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX,
|
||||
// only allow even regs for floats (allow for doubles)
|
||||
/* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX,
|
||||
// only allow even regs for floats (allow for doubles)
|
||||
/* st0 */ RC_INT | RC_INT_BSIDE | RC_ST0,
|
||||
/* A4 */ RC_C67_A4,
|
||||
/* A5 */ RC_C67_A5,
|
||||
@@ -114,67 +156,36 @@ int reg_classes[NB_REGS] = {
|
||||
/* B13 */ RC_C67_B11
|
||||
};
|
||||
|
||||
/* return registers for function */
|
||||
#define REG_IRET TREG_C67_A4 /* single word int return register */
|
||||
#define REG_LRET TREG_C67_A5 /* second word return register (for long long) */
|
||||
#define REG_FRET TREG_C67_A4 /* float return register */
|
||||
|
||||
|
||||
#define ALWAYS_ASSERT(x) \
|
||||
do {\
|
||||
if (!(x))\
|
||||
error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
|
||||
} while (0)
|
||||
|
||||
// although tcc thinks it is passing parameters on the stack,
|
||||
// the C67 really passes up to the first 10 params in special
|
||||
// regs or regs pairs (for 64 bit params). So keep track of
|
||||
// the stack offsets so we can translate to the appropriate
|
||||
// reg (pair)
|
||||
|
||||
|
||||
#define NoCallArgsPassedOnStack 10
|
||||
int NoOfCurFuncArgs;
|
||||
int TranslateStackToReg[NoCallArgsPassedOnStack];
|
||||
int ParamLocOnStack[NoCallArgsPassedOnStack];
|
||||
int TotalBytesPushedOnStack;
|
||||
|
||||
/* defined if function parameters must be evaluated in reverse order */
|
||||
#ifndef FALSE
|
||||
# define FALSE 0
|
||||
# define TRUE 1
|
||||
#endif
|
||||
|
||||
//#define INVERT_FUNC_PARAMS
|
||||
#undef BOOL
|
||||
#define BOOL int
|
||||
|
||||
/* defined if structures are passed as pointers. Otherwise structures
|
||||
are directly pushed on stack. */
|
||||
//#define FUNC_STRUCT_PARAM_AS_PTR
|
||||
|
||||
/* pointer size, in bytes */
|
||||
#define PTR_SIZE 4
|
||||
|
||||
/* long double size and alignment, in bytes */
|
||||
#define LDOUBLE_SIZE 12
|
||||
#define LDOUBLE_ALIGN 4
|
||||
/* maximum alignment (for aligned attribute support) */
|
||||
#define MAX_ALIGN 8
|
||||
#define ALWAYS_ASSERT(x) \
|
||||
do {\
|
||||
if (!(x))\
|
||||
tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
|
||||
} while (0)
|
||||
|
||||
/******************************************************/
|
||||
/* ELF defines */
|
||||
|
||||
#define EM_TCC_TARGET EM_C60
|
||||
|
||||
/* relocation type for 32 bit data relocation */
|
||||
#define R_DATA_32 R_C60_32
|
||||
#define R_JMP_SLOT R_C60_JMP_SLOT
|
||||
#define R_COPY R_C60_COPY
|
||||
|
||||
#define ELF_START_ADDR 0x00000400
|
||||
#define ELF_PAGE_SIZE 0x1000
|
||||
|
||||
/******************************************************/
|
||||
|
||||
static unsigned long func_sub_sp_offset;
|
||||
static int func_ret_sub;
|
||||
|
||||
|
||||
static BOOL C67_invert_test;
|
||||
static int C67_compare_reg;
|
||||
|
||||
@@ -182,7 +193,6 @@ static int C67_compare_reg;
|
||||
FILE *f = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
void C67_g(int c)
|
||||
{
|
||||
int ind1;
|
||||
@@ -1552,7 +1562,7 @@ void C67_SHR(int r, int v)
|
||||
void load(int r, SValue * sv)
|
||||
{
|
||||
int v, t, ft, fc, fr, size = 0, element;
|
||||
BOOL Unsigned = false;
|
||||
BOOL Unsigned = FALSE;
|
||||
SValue v1;
|
||||
|
||||
fr = sv->r;
|
||||
@@ -1568,7 +1578,7 @@ void load(int r, SValue * sv)
|
||||
load(r, &v1);
|
||||
fr = r;
|
||||
} else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
|
||||
error("long double not supported");
|
||||
tcc_error("long double not supported");
|
||||
} else if ((ft & VT_TYPE) == VT_BYTE) {
|
||||
size = 1;
|
||||
} else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
|
||||
@@ -1722,7 +1732,7 @@ void store(int r, SValue * v)
|
||||
/* XXX: incorrect if float reg to reg */
|
||||
|
||||
if (bt == VT_LDOUBLE) {
|
||||
error("long double not supported");
|
||||
tcc_error("long double not supported");
|
||||
} else {
|
||||
if (bt == VT_SHORT)
|
||||
size = 2;
|
||||
@@ -1877,7 +1887,7 @@ void gfunc_call(int nb_args)
|
||||
int args_sizes[NoCallArgsPassedOnStack];
|
||||
|
||||
if (nb_args > NoCallArgsPassedOnStack) {
|
||||
error("more than 10 function params not currently supported");
|
||||
tcc_error("more than 10 function params not currently supported");
|
||||
// handle more than 10, put some on the stack
|
||||
}
|
||||
|
||||
@@ -1892,9 +1902,9 @@ void gfunc_call(int nb_args)
|
||||
|
||||
|
||||
if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
|
||||
error("long long not supported");
|
||||
tcc_error("long long not supported");
|
||||
} else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
|
||||
error("long double not supported");
|
||||
tcc_error("long double not supported");
|
||||
} else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
|
||||
size = 8;
|
||||
} else {
|
||||
@@ -2178,34 +2188,34 @@ void gen_opi(int op)
|
||||
|
||||
if (op == TOK_LT) {
|
||||
C67_CMPLT(r, fr, C67_B2);
|
||||
C67_invert_test = false;
|
||||
C67_invert_test = FALSE;
|
||||
} else if (op == TOK_GE) {
|
||||
C67_CMPLT(r, fr, C67_B2);
|
||||
C67_invert_test = true;
|
||||
C67_invert_test = TRUE;
|
||||
} else if (op == TOK_GT) {
|
||||
C67_CMPGT(r, fr, C67_B2);
|
||||
C67_invert_test = false;
|
||||
C67_invert_test = FALSE;
|
||||
} else if (op == TOK_LE) {
|
||||
C67_CMPGT(r, fr, C67_B2);
|
||||
C67_invert_test = true;
|
||||
C67_invert_test = TRUE;
|
||||
} else if (op == TOK_EQ) {
|
||||
C67_CMPEQ(r, fr, C67_B2);
|
||||
C67_invert_test = false;
|
||||
C67_invert_test = FALSE;
|
||||
} else if (op == TOK_NE) {
|
||||
C67_CMPEQ(r, fr, C67_B2);
|
||||
C67_invert_test = true;
|
||||
C67_invert_test = TRUE;
|
||||
} else if (op == TOK_ULT) {
|
||||
C67_CMPLTU(r, fr, C67_B2);
|
||||
C67_invert_test = false;
|
||||
C67_invert_test = FALSE;
|
||||
} else if (op == TOK_UGE) {
|
||||
C67_CMPLTU(r, fr, C67_B2);
|
||||
C67_invert_test = true;
|
||||
C67_invert_test = TRUE;
|
||||
} else if (op == TOK_UGT) {
|
||||
C67_CMPGTU(r, fr, C67_B2);
|
||||
C67_invert_test = false;
|
||||
C67_invert_test = FALSE;
|
||||
} else if (op == TOK_ULE) {
|
||||
C67_CMPGTU(r, fr, C67_B2);
|
||||
C67_invert_test = true;
|
||||
C67_invert_test = TRUE;
|
||||
} else if (op == '+')
|
||||
C67_ADD(fr, r); // ADD r,fr,r
|
||||
else if (op == '-')
|
||||
@@ -2325,7 +2335,7 @@ void gen_opf(int op)
|
||||
|
||||
|
||||
if ((ft & VT_BTYPE) == VT_LDOUBLE)
|
||||
error("long doubles not supported");
|
||||
tcc_error("long doubles not supported");
|
||||
|
||||
if (op >= TOK_ULT && op <= TOK_GT) {
|
||||
|
||||
@@ -2340,42 +2350,42 @@ void gen_opf(int op)
|
||||
else
|
||||
C67_CMPLTSP(r, fr, C67_B2);
|
||||
|
||||
C67_invert_test = false;
|
||||
C67_invert_test = FALSE;
|
||||
} else if (op == TOK_GE) {
|
||||
if ((ft & VT_BTYPE) == VT_DOUBLE)
|
||||
C67_CMPLTDP(r, fr, C67_B2);
|
||||
else
|
||||
C67_CMPLTSP(r, fr, C67_B2);
|
||||
|
||||
C67_invert_test = true;
|
||||
C67_invert_test = TRUE;
|
||||
} else if (op == TOK_GT) {
|
||||
if ((ft & VT_BTYPE) == VT_DOUBLE)
|
||||
C67_CMPGTDP(r, fr, C67_B2);
|
||||
else
|
||||
C67_CMPGTSP(r, fr, C67_B2);
|
||||
|
||||
C67_invert_test = false;
|
||||
C67_invert_test = FALSE;
|
||||
} else if (op == TOK_LE) {
|
||||
if ((ft & VT_BTYPE) == VT_DOUBLE)
|
||||
C67_CMPGTDP(r, fr, C67_B2);
|
||||
else
|
||||
C67_CMPGTSP(r, fr, C67_B2);
|
||||
|
||||
C67_invert_test = true;
|
||||
C67_invert_test = TRUE;
|
||||
} else if (op == TOK_EQ) {
|
||||
if ((ft & VT_BTYPE) == VT_DOUBLE)
|
||||
C67_CMPEQDP(r, fr, C67_B2);
|
||||
else
|
||||
C67_CMPEQSP(r, fr, C67_B2);
|
||||
|
||||
C67_invert_test = false;
|
||||
C67_invert_test = FALSE;
|
||||
} else if (op == TOK_NE) {
|
||||
if ((ft & VT_BTYPE) == VT_DOUBLE)
|
||||
C67_CMPEQDP(r, fr, C67_B2);
|
||||
else
|
||||
C67_CMPEQSP(r, fr, C67_B2);
|
||||
|
||||
C67_invert_test = true;
|
||||
C67_invert_test = TRUE;
|
||||
} else {
|
||||
ALWAYS_ASSERT(FALSE);
|
||||
}
|
||||
@@ -2477,7 +2487,7 @@ void gen_cvt_ftoi(int t)
|
||||
r = vtop->r;
|
||||
|
||||
if (t != VT_INT)
|
||||
error("long long not supported");
|
||||
tcc_error("long long not supported");
|
||||
else {
|
||||
if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
|
||||
C67_DPTRUNC(r, r);
|
||||
@@ -2544,5 +2554,7 @@ void ggoto(void)
|
||||
vtop--;
|
||||
}
|
||||
|
||||
/* end of X86 code generator */
|
||||
/* end of C67 code generator */
|
||||
/*************************************************************/
|
||||
#endif
|
||||
/*************************************************************/
|
||||
|
||||
582
configure
vendored
582
configure
vendored
@@ -1,21 +1,20 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# tcc configure script (c) 2003 Fabrice Bellard
|
||||
#
|
||||
# set temporary file name
|
||||
if test ! -z "$TMPDIR" ; then
|
||||
TMPDIR1="${TMPDIR}"
|
||||
elif test ! -z "$TEMPDIR" ; then
|
||||
TMPDIR1="${TEMPDIR}"
|
||||
else
|
||||
TMPDIR1="/tmp"
|
||||
fi
|
||||
|
||||
TMPC="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}.c"
|
||||
TMPO="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}.o"
|
||||
TMPE="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}"
|
||||
TMPS="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}.S"
|
||||
TMPH="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}.h"
|
||||
# set temporary file name
|
||||
# if test ! -z "$TMPDIR" ; then
|
||||
# TMPDIR1="${TMPDIR}"
|
||||
# elif test ! -z "$TEMPDIR" ; then
|
||||
# TMPDIR1="${TEMPDIR}"
|
||||
# else
|
||||
# TMPDIR1="/tmp"
|
||||
# fi
|
||||
#
|
||||
# bashism: TMPN="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}.c"
|
||||
|
||||
TMPN="./conftest-$$"
|
||||
TMPH=$TMPN.h
|
||||
|
||||
# default parameters
|
||||
build_cross="no"
|
||||
@@ -27,21 +26,70 @@ libdir=""
|
||||
tccdir=""
|
||||
includedir=""
|
||||
mandir=""
|
||||
infodir=""
|
||||
sysroot=""
|
||||
cross_prefix=""
|
||||
cc="gcc"
|
||||
host_cc="gcc"
|
||||
ar="ar"
|
||||
strip="strip"
|
||||
cygwin="no"
|
||||
gprof="no"
|
||||
bigendian="no"
|
||||
mingw32="no"
|
||||
LIBSUF=".a"
|
||||
EXESUF=""
|
||||
tcc_sysincludepaths=""
|
||||
tcc_libpaths=""
|
||||
tcc_crtprefix=""
|
||||
tcc_elfinterp=""
|
||||
tcc_lddir=
|
||||
confvars=
|
||||
|
||||
cpu=`uname -m`
|
||||
|
||||
# OS specific
|
||||
targetos=`uname -s`
|
||||
case $targetos in
|
||||
MINGW32*) mingw32=yes;;
|
||||
DragonFly) noldl=yes;;
|
||||
OpenBSD) noldl=yes;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
# find source path
|
||||
# XXX: we assume an absolute path is given when launching configure,
|
||||
# except in './configure' case.
|
||||
source_path=${0%configure}
|
||||
source_path=${source_path%/}
|
||||
source_path_used="yes"
|
||||
if test -z "$source_path" -o "$source_path" = "." ; then
|
||||
source_path=`pwd`
|
||||
source_path_used="no"
|
||||
fi
|
||||
|
||||
case "$cpu" in
|
||||
i386|i486|i586|i686|i86pc|BePC)
|
||||
i386|i486|i586|i686|i86pc|BePC|i686-AT386)
|
||||
cpu="x86"
|
||||
;;
|
||||
x86_64)
|
||||
cpu="x86-64"
|
||||
;;
|
||||
armv4l)
|
||||
arm*)
|
||||
case "$cpu" in
|
||||
arm|armv4l)
|
||||
cpuver=4
|
||||
;;
|
||||
armv5tel|armv5tejl)
|
||||
cpuver=5
|
||||
;;
|
||||
armv6j|armv6l)
|
||||
cpuver=6
|
||||
;;
|
||||
armv7a|armv7l)
|
||||
cpuver=7
|
||||
;;
|
||||
esac
|
||||
cpu="armv4l"
|
||||
;;
|
||||
alpha)
|
||||
@@ -60,52 +108,30 @@ case "$cpu" in
|
||||
cpu="unknown"
|
||||
;;
|
||||
esac
|
||||
gprof="no"
|
||||
bigendian="no"
|
||||
mingw32="no"
|
||||
LIBSUF=".a"
|
||||
EXESUF=""
|
||||
|
||||
# OS specific
|
||||
targetos=`uname -s`
|
||||
case $targetos in
|
||||
MINGW32*)
|
||||
mingw32="yes"
|
||||
;;
|
||||
DragonFly)
|
||||
noldl="yes"
|
||||
;;
|
||||
OpenBSD)
|
||||
noldl="yes"
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
# find source path
|
||||
# XXX: we assume an absolute path is given when launching configure,
|
||||
# except in './configure' case.
|
||||
source_path=${0%configure}
|
||||
source_path=${source_path%/}
|
||||
source_path_used="yes"
|
||||
if test -z "$source_path" -o "$source_path" = "." ; then
|
||||
source_path=`pwd`
|
||||
source_path_used="no"
|
||||
fi
|
||||
|
||||
for opt do
|
||||
eval opt=\"$opt\"
|
||||
case "$opt" in
|
||||
--prefix=*) prefix=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--exec-prefix=*) execprefix=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--tccdir=*) tccdir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--bindir=*) bindir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--libdir=*) libdir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--includedir=*) includedir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--sharedir=*) sharedir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--mandir=*) mandir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--infodir=*) infodir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--docdir=*) docdir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--sysroot=*) sysroot=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--source-path=*) source_path=`echo $opt | cut -d '=' -f 2`
|
||||
@@ -120,193 +146,270 @@ for opt do
|
||||
;;
|
||||
--extra-libs=*) extralibs=${opt#--extra-libs=}
|
||||
;;
|
||||
--sysincludepaths=*) tcc_sysincludepaths=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--libpaths=*) tcc_libpaths=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--crtprefix=*) tcc_crtprefix=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--elfinterp=*) tcc_elfinterp=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--enable-gprof) gprof="yes"
|
||||
;;
|
||||
--enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-"
|
||||
;;
|
||||
--enable-mingw32) mingw32="yes" ; cross_prefix="i686-pc-mingw32-" ; cpu=x86
|
||||
;;
|
||||
--enable-cygwin) mingw32="yes" ; cygwin="yes" ; cross_prefix="mingw32-" ; cpu=x86
|
||||
;;
|
||||
--enable-cross) build_cross="yes"
|
||||
;;
|
||||
--disable-static) disable_static="yes"
|
||||
;;
|
||||
--disable-rpath) disable_rpath="yes"
|
||||
;;
|
||||
--strip-binaries) strip_binaries="yes"
|
||||
;;
|
||||
--with-libgcc) use_libgcc="yes"
|
||||
;;
|
||||
--with-selinux) have_selinux="yes"
|
||||
;;
|
||||
--help|-h) show_help="yes"
|
||||
;;
|
||||
*) echo "configure: WARNING: unrecognized option $opt"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Checking for CFLAGS
|
||||
if test -z "$CFLAGS"; then
|
||||
CFLAGS="-O2"
|
||||
CFLAGS="-Wall -g -O2"
|
||||
fi
|
||||
|
||||
if test "$mingw32" = "yes" ; then
|
||||
if test x"$tccdir" = x""; then
|
||||
tccdir="tcc"
|
||||
fi
|
||||
if test -z "$prefix" ; then
|
||||
prefix="C:/Program Files/${tccdir}"
|
||||
fi
|
||||
if test -z "$sharedir" ; then
|
||||
sharedir="${prefix}"
|
||||
fi
|
||||
execprefix="$prefix"
|
||||
bindir="${prefix}"
|
||||
tccdir="${prefix}"
|
||||
libdir="${prefix}/lib"
|
||||
docdir="${sharedir}/doc"
|
||||
mandir="${sharedir}/man"
|
||||
infodir="${sharedir}/info"
|
||||
LIBSUF=".lib"
|
||||
EXESUF=".exe"
|
||||
else
|
||||
if test -z "$prefix" ; then
|
||||
prefix="/usr/local"
|
||||
fi
|
||||
if test -z "$sharedir" ; then
|
||||
sharedir="${prefix}/share"
|
||||
fi
|
||||
if test x"$execprefix" = x""; then
|
||||
execprefix="${prefix}"
|
||||
fi
|
||||
if test x"$libdir" = x""; then
|
||||
libdir="${execprefix}/lib"
|
||||
fi
|
||||
if test x"$bindir" = x""; then
|
||||
bindir="${execprefix}/bin"
|
||||
fi
|
||||
if test x"$tccdir" = x""; then
|
||||
tccdir="tcc"
|
||||
fi
|
||||
if test x"$docdir" = x""; then
|
||||
docdir="${sharedir}/doc/${tccdir}"
|
||||
fi
|
||||
if test x"$mandir" = x""; then
|
||||
mandir="${sharedir}/man"
|
||||
fi
|
||||
if test x"$infodir" = x""; then
|
||||
infodir="${sharedir}/info"
|
||||
fi
|
||||
tccdir="${libdir}/${tccdir}"
|
||||
fi # mingw32
|
||||
|
||||
if test x"$includedir" = x""; then
|
||||
includedir="${prefix}/include"
|
||||
fi
|
||||
|
||||
if test x"$show_help" = "xyes" ; then
|
||||
cat << EOF
|
||||
Usage: configure [options]
|
||||
Options: [defaults in brackets after descriptions]
|
||||
|
||||
Standard options:
|
||||
--help print this message
|
||||
--prefix=PREFIX install in PREFIX [$prefix]
|
||||
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
|
||||
[same as prefix]
|
||||
--bindir=DIR user executables in DIR [EPREFIX/bin]
|
||||
--libdir=DIR object code libraries in DIR [EPREFIX/lib]
|
||||
--tccdir=DIR installation directory [EPREFIX/lib/tcc]
|
||||
--includedir=DIR C header files in DIR [PREFIX/include]
|
||||
--sharedir=DIR documentation root DIR [PREFIX/share]
|
||||
--docdir=DIR documentation in DIR [SHAREDIR/doc/tcc]
|
||||
--mandir=DIR man documentation in DIR [SHAREDIR/man]
|
||||
--infodir=DIR info documentation in DIR [SHAREDIR/info]
|
||||
|
||||
Advanced options (experts only):
|
||||
--source-path=PATH path of source code [$source_path]
|
||||
--cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
|
||||
--sysroot=PREFIX prepend PREFIX to library/include paths []
|
||||
--cc=CC use C compiler CC [$cc]
|
||||
--extra-cflags= specify compiler flags [$CFLAGS]
|
||||
--extra-ldflags= specify linker options []
|
||||
--strip-binaries strip symbol tables from resulting binaries
|
||||
--disable-static make libtcc.so instead of libtcc.a
|
||||
--disable-rpath disable use of -rpath with the above
|
||||
--with-libgcc use /lib/libgcc_s.so.1 instead of libtcc.a
|
||||
--enable-mingw32 build windows version on linux with mingw32
|
||||
--enable-cygwin build windows version on windows with cygwin
|
||||
--enable-cross build cross compilers
|
||||
--with-selinux use mmap for exec mem [needs writable /tmp]
|
||||
--sysincludepaths=... specify system include paths, colon separated
|
||||
--libpaths=... specify system library paths, colon separated
|
||||
--crtprefix=... specify locations of crt?.o, colon separated
|
||||
--elfinterp=... specify elf interpreter
|
||||
EOF
|
||||
#echo "NOTE: The object files are build at the place where configure is launched"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cc="${cross_prefix}${cc}"
|
||||
ar="${cross_prefix}${ar}"
|
||||
strip="${cross_prefix}${strip}"
|
||||
|
||||
if test "$mingw32" = "yes" ; then
|
||||
LIBSUF=".lib"
|
||||
EXESUF=".exe"
|
||||
fi
|
||||
CONFTEST=./conftest$EXESUF
|
||||
|
||||
if test -z "$cross_prefix" ; then
|
||||
if ! $cc -o $CONFTEST $source_path/conftest.c 2>/dev/null ; then
|
||||
echo "configure: error: '$cc' failed to compile conftest.c."
|
||||
else
|
||||
bigendian="$($CONFTEST bigendian)"
|
||||
gcc_major="$($CONFTEST version)"
|
||||
gcc_minor="$($CONFTEST minor)"
|
||||
if test "$mingw32" = "no" ; then
|
||||
triplet="$($CONFTEST triplet)"
|
||||
if test -f "/usr/lib/$triplet/crti.o" ; then
|
||||
tcc_lddir="lib/$triplet"
|
||||
multiarch_triplet="$triplet"
|
||||
elif test -f "/usr/lib64/crti.o" ; then
|
||||
tcc_lddir="lib64"
|
||||
fi
|
||||
|
||||
# ---
|
||||
# big/little endian test
|
||||
cat > $TMPC << EOF
|
||||
#include <inttypes.h>
|
||||
int main(int argc, char ** argv){
|
||||
volatile uint32_t i=0x01234567;
|
||||
return (*((uint8_t*)(&i))) == 0x67;
|
||||
}
|
||||
EOF
|
||||
if test "$cpu" = "armv4l" ; then
|
||||
if test "${triplet%eabihf}" != "$triplet" ; then
|
||||
confvars="$confvars arm_eabihf"
|
||||
elif test "${triplet%eabi}" != "$triplet" ; then
|
||||
confvars="$confvars arm_eabi"
|
||||
fi
|
||||
if grep -s -q "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo ; then
|
||||
confvars="$confvars arm_vfp"
|
||||
fi
|
||||
fi
|
||||
|
||||
if $cc -o $TMPE $TMPC 2>/dev/null ; then
|
||||
$TMPE && bigendian="yes"
|
||||
# multiarch_triplet=${libc_dir#*/}
|
||||
# multiarch_triplet=${multiarch_triplet%/}
|
||||
# tcc_lddir="${libc_dir%%/*}"
|
||||
# if test -n "$multiarch_triplet" ; then
|
||||
# tcc_lddir="$tcc_lddir/$multiarch_triplet"
|
||||
# fi
|
||||
|
||||
if test -f "/lib/ld-uClibc.so.0" ; then
|
||||
confvars="$confvars uClibc"
|
||||
fi
|
||||
# gr: maybe for after the release:
|
||||
# tcc_elfinterp="$(ldd $CONFTEST | grep 'ld.*.so' | sed 's,\s*\(\S\+\).*,\1,')"
|
||||
# echo "elfinterp $tcc_elfinterp"
|
||||
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo big/little test failed
|
||||
# if cross compiling, cannot launch a program, so make a static guess
|
||||
case $cpu in
|
||||
powerpc|mips|s390) bigendian=yes;;
|
||||
esac
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
# if cross compiling, cannot launch a program, so make a static guess
|
||||
if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" ; then
|
||||
bigendian="yes"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# check gcc version
|
||||
cat > $TMPC <<EOF
|
||||
int main(void) {
|
||||
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)
|
||||
return 0;
|
||||
#else
|
||||
#error gcc < 3.2
|
||||
#endif
|
||||
}
|
||||
cat <<EOF
|
||||
Binary directory $bindir
|
||||
TinyCC directory $tccdir
|
||||
Library directory $libdir
|
||||
Include directory $includedir
|
||||
Manual directory $mandir
|
||||
Info directory $infodir
|
||||
Doc directory $docdir
|
||||
Target root prefix $sysroot
|
||||
Source path $source_path
|
||||
C compiler $cc
|
||||
Target OS $targetos
|
||||
CPU $cpu
|
||||
Big Endian $bigendian
|
||||
gprof enabled $gprof
|
||||
cross compilers $build_cross
|
||||
use libgcc $use_libgcc
|
||||
EOF
|
||||
|
||||
gcc_major="2"
|
||||
if $cc -o $TMPO $TMPC 2> /dev/null ; then
|
||||
gcc_major="3"
|
||||
fi
|
||||
cat > $TMPC <<EOF
|
||||
int main(void) {
|
||||
#if __GNUC__ >= 4
|
||||
return 0;
|
||||
#else
|
||||
#error gcc < 4
|
||||
#endif
|
||||
}
|
||||
EOF
|
||||
|
||||
if $cc -o $TMPO $TMPC 2> /dev/null ; then
|
||||
gcc_major="4"
|
||||
fi
|
||||
|
||||
if test x"$1" = x"-h" -o x"$1" = x"--help" ; then
|
||||
cat << EOF
|
||||
|
||||
Usage: configure [options]
|
||||
Options: [defaults in brackets after descriptions]
|
||||
|
||||
EOF
|
||||
echo "Standard options:"
|
||||
echo " --help print this message"
|
||||
echo " --prefix=PREFIX install in PREFIX [$prefix]"
|
||||
echo " --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX"
|
||||
echo " [same as prefix]"
|
||||
echo " --bindir=DIR user executables in DIR [EPREFIX/bin]"
|
||||
echo " --libdir=DIR object code libraries in DIR [EPREFIX/lib]"
|
||||
echo " --includedir=DIR C header files in DIR [PREFIX/include]"
|
||||
echo " --mandir=DIR man documentation in DIR [PREFIX/man]"
|
||||
echo " --enable-cross build cross compilers"
|
||||
echo ""
|
||||
echo "Advanced options (experts only):"
|
||||
echo " --source-path=PATH path of source code [$source_path]"
|
||||
echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]"
|
||||
echo " --sysroot=PREFIX prepend PREFIX to library/include paths []"
|
||||
echo " --cc=CC use C compiler CC [$cc]"
|
||||
echo " --with-libgcc use /lib/libgcc_s.so.1 instead of libtcc1.a"
|
||||
echo ""
|
||||
#echo "NOTE: The object files are build at the place where configure is launched"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test "$mingw32" = "yes" ; then
|
||||
if test -z "$prefix" ; then
|
||||
prefix="C:/Program Files/tcc"
|
||||
fi
|
||||
execprefix="$prefix"
|
||||
bindir="$prefix"
|
||||
tccdir="$prefix"
|
||||
docdir="$prefix/doc"
|
||||
else
|
||||
if test -z "$prefix" ; then
|
||||
prefix="/usr/local"
|
||||
fi
|
||||
if test x"$execprefix" = x""; then
|
||||
execprefix="${prefix}"
|
||||
fi
|
||||
if test x"$bindir" = x""; then
|
||||
bindir="${execprefix}/bin"
|
||||
fi
|
||||
if test x"$docdir" = x""; then
|
||||
docdir="$prefix/share/doc/tcc"
|
||||
fi
|
||||
fi # mingw32
|
||||
|
||||
if test x"$libdir" = x""; then
|
||||
libdir="${execprefix}/lib"
|
||||
fi
|
||||
if test x"$tccdir" = x""; then
|
||||
tccdir="${execprefix}/lib/tcc"
|
||||
fi
|
||||
if test x"$mandir" = x""; then
|
||||
mandir="${prefix}/man"
|
||||
fi
|
||||
if test x"$includedir" = x""; then
|
||||
includedir="${prefix}/include"
|
||||
fi
|
||||
|
||||
echo "Binary directory $bindir"
|
||||
echo "TinyCC directory $tccdir"
|
||||
echo "Library directory $libdir"
|
||||
echo "Include directory $includedir"
|
||||
echo "Manual directory $mandir"
|
||||
echo "Doc directory $docdir"
|
||||
echo "Target root prefix $sysroot"
|
||||
echo "Source path $source_path"
|
||||
echo "C compiler $cc"
|
||||
echo "CPU $cpu"
|
||||
echo "Big Endian $bigendian"
|
||||
echo "gprof enabled $gprof"
|
||||
echo "cross compilers $build_cross"
|
||||
echo "use libgcc $use_libgcc"
|
||||
|
||||
echo "Creating config.mak and config.h"
|
||||
|
||||
echo "# Automatically generated by configure - do not modify" > config.mak
|
||||
cat >config.mak <<EOF
|
||||
# Automatically generated by configure - do not modify
|
||||
prefix=$prefix
|
||||
bindir=\$(DESTDIR)$bindir
|
||||
tccdir=\$(DESTDIR)$tccdir
|
||||
libdir=\$(DESTDIR)$libdir
|
||||
ln_libdir=$libdir
|
||||
includedir=\$(DESTDIR)$includedir
|
||||
mandir=\$(DESTDIR)$mandir
|
||||
infodir=\$(DESTDIR)$infodir
|
||||
docdir=\$(DESTDIR)$docdir
|
||||
CC=$cc
|
||||
GCC_MAJOR=$gcc_major
|
||||
GCC_MINOR=$gcc_minor
|
||||
HOST_CC=$host_cc
|
||||
AR=$ar
|
||||
STRIP=$strip -s -R .comment -R .note
|
||||
CFLAGS=$CFLAGS
|
||||
LDFLAGS=$LDFLAGS
|
||||
LIBSUF=$LIBSUF
|
||||
EXESUF=$EXESUF
|
||||
EOF
|
||||
|
||||
print_inc() {
|
||||
if test -n "$2"; then
|
||||
echo "#ifndef $1" >> $TMPH
|
||||
echo "# define $1 \"$2\"" >> $TMPH
|
||||
echo "#endif" >> $TMPH
|
||||
fi
|
||||
}
|
||||
print_mak() {
|
||||
if test -n "$2"; then
|
||||
echo "NATIVE_DEFINES+=-D$1=\"\\\"$2\\\"\"" >> config.mak
|
||||
fi
|
||||
}
|
||||
|
||||
echo "/* Automatically generated by configure - do not modify */" > $TMPH
|
||||
|
||||
echo "prefix=$prefix" >> config.mak
|
||||
echo "bindir=$bindir" >> config.mak
|
||||
echo "tccdir=$tccdir" >> config.mak
|
||||
echo "libdir=$libdir" >> config.mak
|
||||
echo "includedir=$includedir" >> config.mak
|
||||
echo "mandir=$mandir" >> config.mak
|
||||
echo "docdir=$docdir" >> config.mak
|
||||
echo "#define CONFIG_SYSROOT \"$sysroot\"" >> $TMPH
|
||||
echo "#define CONFIG_TCCDIR \"$tccdir\"" >> $TMPH
|
||||
echo "CC=$cc" >> config.mak
|
||||
echo "GCC_MAJOR=$gcc_major" >> config.mak
|
||||
print_inc CONFIG_SYSROOT "$sysroot"
|
||||
print_inc CONFIG_TCCDIR "$tccdir"
|
||||
print_mak CONFIG_TCC_SYSINCLUDEPATHS "$tcc_sysincludepaths"
|
||||
print_mak CONFIG_TCC_LIBPATHS "$tcc_libpaths"
|
||||
print_mak CONFIG_TCC_CRTPREFIX "$tcc_crtprefix"
|
||||
print_mak CONFIG_TCC_ELFINTERP "$tcc_elfinterp"
|
||||
print_mak CONFIG_LDDIR "$tcc_lddir"
|
||||
print_mak CONFIG_MULTIARCHDIR "$multiarch_triplet"
|
||||
|
||||
echo "#define GCC_MAJOR $gcc_major" >> $TMPH
|
||||
echo "HOST_CC=$host_cc" >> config.mak
|
||||
echo "AR=$ar" >> config.mak
|
||||
echo "STRIP=$strip -s -R .comment -R .note" >> config.mak
|
||||
echo "CFLAGS=$CFLAGS" >> config.mak
|
||||
echo "LDFLAGS=$LDFLAGS" >> config.mak
|
||||
echo "LIBSUF=$LIBSUF" >> config.mak
|
||||
echo "EXESUF=$EXESUF" >> config.mak
|
||||
echo "#define GCC_MINOR $gcc_minor" >> $TMPH
|
||||
|
||||
if test "$cpu" = "x86" ; then
|
||||
echo "ARCH=i386" >> config.mak
|
||||
echo "#define HOST_I386 1" >> $TMPH
|
||||
@@ -316,6 +419,7 @@ elif test "$cpu" = "x86-64" ; then
|
||||
elif test "$cpu" = "armv4l" ; then
|
||||
echo "ARCH=arm" >> config.mak
|
||||
echo "#define HOST_ARM 1" >> $TMPH
|
||||
echo "#define TCC_ARM_VERSION $cpuver" >> $TMPH
|
||||
elif test "$cpu" = "powerpc" ; then
|
||||
echo "ARCH=ppc" >> config.mak
|
||||
echo "#define HOST_PPC 1" >> $TMPH
|
||||
@@ -332,6 +436,12 @@ else
|
||||
echo "Unsupported CPU"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "TARGETOS=$targetos" >> config.mak
|
||||
|
||||
for v in $confvars ; do
|
||||
echo "CONFIG_$v=yes" >> config.mak
|
||||
done
|
||||
if test "$noldl" = "yes" ; then
|
||||
echo "CONFIG_NOLDL=yes" >> config.mak
|
||||
fi
|
||||
@@ -339,6 +449,12 @@ if test "$mingw32" = "yes" ; then
|
||||
echo "CONFIG_WIN32=yes" >> config.mak
|
||||
echo "#define CONFIG_WIN32 1" >> $TMPH
|
||||
fi
|
||||
if test "$cygwin" = "yes" ; then
|
||||
echo "#ifndef _WIN32" >> $TMPH
|
||||
echo "# define _WIN32" >> $TMPH
|
||||
echo "#endif" >> $TMPH
|
||||
echo "AR=ar" >> config.mak
|
||||
fi
|
||||
if test "$bigendian" = "yes" ; then
|
||||
echo "WORDS_BIGENDIAN=yes" >> config.mak
|
||||
echo "#define WORDS_BIGENDIAN 1" >> $TMPH
|
||||
@@ -350,27 +466,39 @@ fi
|
||||
if test "$build_cross" = "yes" ; then
|
||||
echo "CONFIG_CROSS=yes" >> config.mak
|
||||
fi
|
||||
if test "$disable_static" = "yes" ; then
|
||||
echo "DISABLE_STATIC=yes" >> config.mak
|
||||
fi
|
||||
if test "$disable_rpath" = "yes" ; then
|
||||
echo "DISABLE_RPATH=yes" >> config.mak
|
||||
fi
|
||||
if test "$strip_binaries" = "yes" ; then
|
||||
echo "STRIP_BINARIES=yes" >> config.mak
|
||||
fi
|
||||
if test "$use_libgcc" = "yes" ; then
|
||||
echo "#define CONFIG_USE_LIBGCC" >> $TMPH
|
||||
echo "CONFIG_USE_LIBGCC=yes" >> config.mak
|
||||
fi
|
||||
if test "$have_selinux" = "yes" ; then
|
||||
echo "#define HAVE_SELINUX" >> $TMPH
|
||||
echo "HAVE_SELINUX=yes" >> config.mak
|
||||
fi
|
||||
|
||||
version=`head $source_path/VERSION`
|
||||
echo "VERSION=$version" >>config.mak
|
||||
echo "#define TCC_VERSION \"$version\"" >> $TMPH
|
||||
echo "@set VERSION $version" > config.texi
|
||||
echo "SRC_PATH=$source_path" >>config.mak
|
||||
|
||||
# build tree in object directory if source path is different from current one
|
||||
if test "$source_path_used" = "yes" ; then
|
||||
DIRS="tests"
|
||||
FILES="Makefile tests/Makefile"
|
||||
for dir in $DIRS ; do
|
||||
mkdir -p $dir
|
||||
done
|
||||
for f in $FILES ; do
|
||||
ln -sf $source_path/$f $f
|
||||
done
|
||||
case $source_path in
|
||||
/*) echo "top_srcdir=$source_path";;
|
||||
*) echo "top_srcdir=\$(TOP)/$source_path";;
|
||||
esac >>config.mak
|
||||
else
|
||||
echo 'top_srcdir=$(TOP)' >>config.mak
|
||||
fi
|
||||
echo "SRC_PATH=$source_path" >> config.mak
|
||||
echo 'top_builddir=$(TOP)' >>config.mak
|
||||
|
||||
diff $TMPH config.h >/dev/null 2>&1
|
||||
if test $? -ne 0 ; then
|
||||
@@ -379,4 +507,34 @@ else
|
||||
echo "config.h is unchanged"
|
||||
fi
|
||||
|
||||
rm -f $TMPO $TMPC $TMPE $TMPS $TMPH
|
||||
rm -f $TMPN* $CONFTEST
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# build tree in object directory if source path is different from current one
|
||||
|
||||
fn_makelink()
|
||||
{
|
||||
tgt=$1/$2
|
||||
case $2 in
|
||||
*/*) dn=${2%/*}
|
||||
test -d $dn || mkdir -p $dn
|
||||
case $1 in
|
||||
/*) ;;
|
||||
*) while test $dn ; do
|
||||
tgt=../$tgt; dn=${dn#${dn%%/*}}; dn=${dn#/}
|
||||
done
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
ln -sfn $tgt $2
|
||||
}
|
||||
|
||||
if test "$source_path_used" = "yes" ; then
|
||||
FILES="Makefile lib/Makefile tests/Makefile tests/tests2/Makefile"
|
||||
for f in $FILES ; do
|
||||
fn_makelink $source_path $f
|
||||
done
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
71
conftest.c
Normal file
71
conftest.c
Normal file
@@ -0,0 +1,71 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/* Define architecture */
|
||||
#if defined(__i386__)
|
||||
# define TRIPLET_ARCH "i386"
|
||||
#elif defined(__x86_64__)
|
||||
# define TRIPLET_ARCH "x86_64"
|
||||
#elif defined(__arm__)
|
||||
# define TRIPLET_ARCH "arm"
|
||||
#else
|
||||
# define TRIPLET_ARCH "unknown"
|
||||
#endif
|
||||
|
||||
/* Define OS */
|
||||
#if defined (__linux__)
|
||||
# define TRIPLET_OS "linux"
|
||||
#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
||||
# define TRIPLET_OS "kfreebsd"
|
||||
#elif !defined (__GNU__)
|
||||
# define TRIPLET_OS "unknown"
|
||||
#endif
|
||||
|
||||
/* Define calling convention and ABI */
|
||||
#if defined (__ARM_EABI__)
|
||||
# if defined (__ARM_PCS_VFP)
|
||||
# define TRIPLET_ABI "gnueabihf"
|
||||
# else
|
||||
# define TRIPLET_ABI "gnueabi"
|
||||
# endif
|
||||
#else
|
||||
# define TRIPLET_ABI "gnu"
|
||||
#endif
|
||||
|
||||
#ifdef __GNU__
|
||||
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_ABI
|
||||
#else
|
||||
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
switch(argc == 2 ? argv[1][0] : 0) {
|
||||
case 'b':
|
||||
{
|
||||
volatile unsigned foo = 0x01234567;
|
||||
puts(*(unsigned char*)&foo == 0x67 ? "no" : "yes");
|
||||
break;
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
case 'm':
|
||||
printf("%d\n", __GNUC_MINOR__);
|
||||
break;
|
||||
case 'v':
|
||||
printf("%d\n", __GNUC__);
|
||||
break;
|
||||
#else
|
||||
case 'm':
|
||||
case 'v':
|
||||
puts("0");
|
||||
break;
|
||||
#endif
|
||||
case 't':
|
||||
puts(TRIPLET);
|
||||
break;
|
||||
case -1:
|
||||
/* to test -Wno-unused-result */
|
||||
fread(NULL, 1, 1, NULL);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
41
elf.h
41
elf.h
@@ -318,7 +318,12 @@ typedef struct
|
||||
#define SHT_REL 9 /* Relocation entries, no addends */
|
||||
#define SHT_SHLIB 10 /* Reserved */
|
||||
#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
|
||||
#define SHT_NUM 12 /* Number of defined types. */
|
||||
#define SHT_INIT_ARRAY 14 /* Array of constructors */
|
||||
#define SHT_FINI_ARRAY 15 /* Array of destructors */
|
||||
#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
|
||||
#define SHT_GROUP 17 /* Section group */
|
||||
#define SHT_SYMTAB_SHNDX 18 /* Extended section indices */
|
||||
#define SHT_NUM 19 /* Number of defined types. */
|
||||
#define SHT_LOOS 0x60000000 /* Start OS-specific */
|
||||
#define SHT_LOSUNW 0x6ffffffb /* Sun-specific low bound. */
|
||||
#define SHT_SUNW_COMDAT 0x6ffffffb
|
||||
@@ -343,6 +348,17 @@ typedef struct
|
||||
#define SHF_EXECINSTR (1 << 2) /* Executable */
|
||||
#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
|
||||
|
||||
#define SHF_MERGE 0x10
|
||||
#define SHF_STRINGS 0x20
|
||||
#define SHF_INFO_LINK 0x40
|
||||
#define SHF_LINK_ORDER 0x80
|
||||
#define SHF_OS_NONCONFORMING 0x100
|
||||
#define SHF_GROUP 0x200
|
||||
#define SHF_TLS 0x400
|
||||
#define SHF_MASKOS 0x0ff00000
|
||||
#define SHF_ORDERED 0x40000000
|
||||
#define SHF_EXCLUDE 0x80000000
|
||||
|
||||
/* Symbol table entry. */
|
||||
|
||||
typedef struct
|
||||
@@ -431,6 +447,7 @@ typedef struct
|
||||
#define STT_SECTION 3 /* Symbol associated with a section */
|
||||
#define STT_FILE 4 /* Symbol's name is file name */
|
||||
#define STT_NUM 5 /* Number of defined types. */
|
||||
#define STT_GNU_IFUNC 10 /* Symbol is a indirect code object */
|
||||
#define STT_LOOS 11 /* Start of OS-specific */
|
||||
#define STT_HIOS 12 /* End of OS-specific */
|
||||
#define STT_LOPROC 13 /* Start of processor-specific */
|
||||
@@ -949,6 +966,10 @@ typedef struct
|
||||
/* Keep this the last entry. */
|
||||
#define R_386_NUM 11
|
||||
|
||||
/* TCC-specific 16-bit relocs. */
|
||||
#define R_386_16 12 /* Direct 16 bit */
|
||||
#define R_386_PC16 13 /* PC relative 16 bit */
|
||||
|
||||
/* SUN SPARC specific definitions. */
|
||||
|
||||
/* Values for Elf64_Ehdr.e_flags. */
|
||||
@@ -1652,7 +1673,7 @@ typedef Elf32_Addr Elf32_Conflict;
|
||||
#define R_ARM_THM_ABS5 7
|
||||
#define R_ARM_ABS8 8 /* Direct 8 bit */
|
||||
#define R_ARM_SBREL32 9
|
||||
#define R_ARM_THM_PC22 10
|
||||
#define R_ARM_THM_CALL 10
|
||||
#define R_ARM_THM_PC8 11
|
||||
#define R_ARM_AMP_VCALL9 12
|
||||
#define R_ARM_SWI24 13
|
||||
@@ -1669,7 +1690,13 @@ typedef Elf32_Addr Elf32_Conflict;
|
||||
#define R_ARM_PLT32 27 /* 32 bit PLT address */
|
||||
#define R_ARM_CALL 28
|
||||
#define R_ARM_JUMP24 29
|
||||
#define R_ARM_THM_JUMP24 30
|
||||
#define R_ARM_V4BX 40
|
||||
#define R_ARM_PREL31 42
|
||||
#define R_ARM_MOVW_ABS_NC 43
|
||||
#define R_ARM_MOVT_ABS 44
|
||||
#define R_ARM_THM_MOVW_ABS_NC 47
|
||||
#define R_ARM_THM_MOVT_ABS 48
|
||||
#define R_ARM_GNU_VTENTRY 100
|
||||
#define R_ARM_GNU_VTINHERIT 101
|
||||
#define R_ARM_THM_PC11 102 /* thumb unconditional branch */
|
||||
@@ -1701,14 +1728,4 @@ typedef Elf32_Addr Elf32_Conflict;
|
||||
#define R_C60HI16 0x55 // high 16 bit MVKH embedded
|
||||
#define R_C60LO16 0x54 // low 16 bit MVKL embedded
|
||||
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
#define TCC_ELFCLASS ELFCLASS64
|
||||
#define ElfW(type) Elf##64##_##type
|
||||
#define ELFW(type) ELF##64##_##type
|
||||
#else
|
||||
#define TCC_ELFCLASS ELFCLASS32
|
||||
#define ElfW(type) Elf##32##_##type
|
||||
#define ELFW(type) ELF##32##_##type
|
||||
#endif
|
||||
|
||||
#endif /* elf.h */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#! /usr/local/bin/tcc -run
|
||||
#!/usr/local/bin/tcc -run
|
||||
#include <tcclib.h>
|
||||
|
||||
int main()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!./tcc -run -L/usr/X11R6/lib -lX11
|
||||
#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
725
i386-asm.c
725
i386-asm.c
File diff suppressed because it is too large
Load Diff
41
i386-asm.h
41
i386-asm.h
@@ -1,12 +1,12 @@
|
||||
DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
|
||||
DEF_ASM_OP0(popa, 0x61)
|
||||
DEF_ASM_OP0(clc, 0xf8)
|
||||
DEF_ASM_OP0(clc, 0xf8) /* must be first OP0 */
|
||||
DEF_ASM_OP0(cld, 0xfc)
|
||||
DEF_ASM_OP0(cli, 0xfa)
|
||||
DEF_ASM_OP0(clts, 0x0f06)
|
||||
DEF_ASM_OP0(cmc, 0xf5)
|
||||
DEF_ASM_OP0(lahf, 0x9f)
|
||||
DEF_ASM_OP0(sahf, 0x9e)
|
||||
DEF_ASM_OP0(pusha, 0x60)
|
||||
DEF_ASM_OP0(popa, 0x61)
|
||||
DEF_ASM_OP0(pushfl, 0x9c)
|
||||
DEF_ASM_OP0(popfl, 0x9d)
|
||||
DEF_ASM_OP0(pushf, 0x9c)
|
||||
@@ -33,8 +33,8 @@
|
||||
DEF_ASM_OP0(iret, 0xcf)
|
||||
DEF_ASM_OP0(rsm, 0x0faa)
|
||||
DEF_ASM_OP0(hlt, 0xf4)
|
||||
DEF_ASM_OP0(wait, 0x9b)
|
||||
DEF_ASM_OP0(nop, 0x90)
|
||||
DEF_ASM_OP0(pause, 0xf390)
|
||||
DEF_ASM_OP0(xlat, 0xd7)
|
||||
|
||||
/* strings */
|
||||
@@ -74,10 +74,17 @@ ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA
|
||||
ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
|
||||
|
||||
/* prefixes */
|
||||
DEF_ASM_OP0(wait, 0x9b)
|
||||
DEF_ASM_OP0(fwait, 0x9b)
|
||||
#ifdef I386_ASM_16
|
||||
DEF_ASM_OP0(a32, 0x67)
|
||||
DEF_ASM_OP0(o32, 0x66)
|
||||
#else
|
||||
DEF_ASM_OP0(aword, 0x67)
|
||||
DEF_ASM_OP0(addr16, 0x67)
|
||||
DEF_ASM_OP0(word, 0x66)
|
||||
ALT(DEF_ASM_OP0(word, 0x66))
|
||||
DEF_ASM_OP0(data16, 0x66)
|
||||
#endif
|
||||
DEF_ASM_OP0(lock, 0xf0)
|
||||
DEF_ASM_OP0(rep, 0xf3)
|
||||
DEF_ASM_OP0(repe, 0xf3)
|
||||
@@ -201,6 +208,9 @@ ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
|
||||
ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
|
||||
ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
|
||||
ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
|
||||
#ifdef I386_ASM_16
|
||||
ALT(DEF_ASM_OP1(jmp, 0xff, 0, OPC_JMP | OPC_WL, OPT_REGW))
|
||||
#endif
|
||||
|
||||
ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
|
||||
ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
|
||||
@@ -212,6 +222,8 @@ ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
|
||||
DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
|
||||
DEF_ASM_OP0(leave, 0xc9)
|
||||
DEF_ASM_OP0(ret, 0xc3)
|
||||
DEF_ASM_OP0(retl,0xc3)
|
||||
ALT(DEF_ASM_OP1(retl,0xc2, 0, 0, OPT_IM16))
|
||||
ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
|
||||
DEF_ASM_OP0(lret, 0xcb)
|
||||
ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
|
||||
@@ -230,6 +242,8 @@ ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
|
||||
|
||||
ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
|
||||
ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
|
||||
ALT(DEF_ASM_OP2(fadd, 0xdcc0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
|
||||
ALT(DEF_ASM_OP2(fmul, 0xdcc8, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
|
||||
ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
|
||||
ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
|
||||
ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
|
||||
@@ -272,7 +286,6 @@ ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
|
||||
DEF_ASM_OP0(fninit, 0xdbe3)
|
||||
DEF_ASM_OP0(fnclex, 0xdbe2)
|
||||
DEF_ASM_OP0(fnop, 0xd9d0)
|
||||
DEF_ASM_OP0(fwait, 0x9b)
|
||||
|
||||
/* fp load */
|
||||
DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
|
||||
@@ -350,6 +363,11 @@ ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
|
||||
DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
|
||||
DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
|
||||
|
||||
#ifdef I386_ASM_16
|
||||
/* 386 */
|
||||
DEF_ASM_OP0(loadall386, 0x0f07)
|
||||
#endif
|
||||
|
||||
/* 486 */
|
||||
DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
|
||||
ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
|
||||
@@ -364,7 +382,15 @@ ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT
|
||||
|
||||
/* pentium pro */
|
||||
ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
|
||||
#ifdef I386_ASM_16
|
||||
ALT(DEF_ASM_OP2(cmovno, 0x0f41, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(cmovc, 0x0f42, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(cmovnc, 0x0f43, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(cmovz, 0x0f44, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(cmovnz, 0x0f45, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(cmovna, 0x0f46, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(cmova, 0x0f47, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
#endif
|
||||
DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
@@ -381,6 +407,7 @@ ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT
|
||||
|
||||
/* mmx */
|
||||
DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
|
||||
|
||||
DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
|
||||
ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
|
||||
DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
|
||||
|
||||
146
i386-gen.c
146
i386-gen.c
@@ -18,8 +18,11 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef TARGET_DEFS_ONLY
|
||||
|
||||
/* number of available registers */
|
||||
#define NB_REGS 4
|
||||
#define NB_REGS 4
|
||||
#define NB_ASM_REGS 8
|
||||
|
||||
/* a register can belong to several classes. The classes must be
|
||||
sorted from more general to more precise (see gv2() code which does
|
||||
@@ -42,13 +45,6 @@ enum {
|
||||
TREG_ST0,
|
||||
};
|
||||
|
||||
int reg_classes[NB_REGS] = {
|
||||
/* eax */ RC_INT | RC_EAX,
|
||||
/* ecx */ RC_INT | RC_ECX,
|
||||
/* edx */ RC_INT | RC_EDX,
|
||||
/* st0 */ RC_FLOAT | RC_ST0,
|
||||
};
|
||||
|
||||
/* return registers for function */
|
||||
#define REG_IRET TREG_EAX /* single word int return register */
|
||||
#define REG_LRET TREG_EDX /* second word return register (for long long) */
|
||||
@@ -70,6 +66,9 @@ int reg_classes[NB_REGS] = {
|
||||
/* maximum alignment (for aligned attribute support) */
|
||||
#define MAX_ALIGN 8
|
||||
|
||||
|
||||
#define psym oad
|
||||
|
||||
/******************************************************/
|
||||
/* ELF defines */
|
||||
|
||||
@@ -77,6 +76,7 @@ int reg_classes[NB_REGS] = {
|
||||
|
||||
/* relocation type for 32 bit data relocation */
|
||||
#define R_DATA_32 R_386_32
|
||||
#define R_DATA_PTR R_386_32
|
||||
#define R_JMP_SLOT R_386_JMP_SLOT
|
||||
#define R_COPY R_386_COPY
|
||||
|
||||
@@ -84,13 +84,25 @@ int reg_classes[NB_REGS] = {
|
||||
#define ELF_PAGE_SIZE 0x1000
|
||||
|
||||
/******************************************************/
|
||||
#else /* ! TARGET_DEFS_ONLY */
|
||||
/******************************************************/
|
||||
#include "tcc.h"
|
||||
|
||||
ST_DATA const int reg_classes[NB_REGS] = {
|
||||
/* eax */ RC_INT | RC_EAX,
|
||||
/* ecx */ RC_INT | RC_ECX,
|
||||
/* edx */ RC_INT | RC_EDX,
|
||||
/* st0 */ RC_FLOAT | RC_ST0,
|
||||
};
|
||||
|
||||
static unsigned long func_sub_sp_offset;
|
||||
static unsigned long func_bound_offset;
|
||||
static int func_ret_sub;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
static unsigned long func_bound_offset;
|
||||
#endif
|
||||
|
||||
/* XXX: make it faster ? */
|
||||
void g(int c)
|
||||
ST_FUNC void g(int c)
|
||||
{
|
||||
int ind1;
|
||||
ind1 = ind + 1;
|
||||
@@ -100,7 +112,7 @@ void g(int c)
|
||||
ind = ind1;
|
||||
}
|
||||
|
||||
void o(unsigned int c)
|
||||
ST_FUNC void o(unsigned int c)
|
||||
{
|
||||
while (c) {
|
||||
g(c);
|
||||
@@ -108,7 +120,13 @@ void o(unsigned int c)
|
||||
}
|
||||
}
|
||||
|
||||
void gen_le32(int c)
|
||||
ST_FUNC void gen_le16(int v)
|
||||
{
|
||||
g(v);
|
||||
g(v >> 8);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_le32(int c)
|
||||
{
|
||||
g(c);
|
||||
g(c >> 8);
|
||||
@@ -117,7 +135,7 @@ void gen_le32(int c)
|
||||
}
|
||||
|
||||
/* output a symbol and patch all calls to it */
|
||||
void gsym_addr(int t, int a)
|
||||
ST_FUNC void gsym_addr(int t, int a)
|
||||
{
|
||||
int n, *ptr;
|
||||
while (t) {
|
||||
@@ -128,7 +146,7 @@ void gsym_addr(int t, int a)
|
||||
}
|
||||
}
|
||||
|
||||
void gsym(int t)
|
||||
ST_FUNC void gsym(int t)
|
||||
{
|
||||
gsym_addr(t, ind);
|
||||
}
|
||||
@@ -138,7 +156,7 @@ void gsym(int t)
|
||||
#define psym oad
|
||||
|
||||
/* instruction + 4 bytes data. Return the address of the data */
|
||||
static int oad(int c, int s)
|
||||
ST_FUNC int oad(int c, int s)
|
||||
{
|
||||
int ind1;
|
||||
|
||||
@@ -153,13 +171,20 @@ static int oad(int c, int s)
|
||||
}
|
||||
|
||||
/* output constant with relocation if 'r & VT_SYM' is true */
|
||||
static void gen_addr32(int r, Sym *sym, int c)
|
||||
ST_FUNC void gen_addr32(int r, Sym *sym, int c)
|
||||
{
|
||||
if (r & VT_SYM)
|
||||
greloc(cur_text_section, sym, ind, R_386_32);
|
||||
gen_le32(c);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
|
||||
{
|
||||
if (r & VT_SYM)
|
||||
greloc(cur_text_section, sym, ind, R_386_PC32);
|
||||
gen_le32(c - 4);
|
||||
}
|
||||
|
||||
/* generate a modrm reference. 'op_reg' contains the addtionnal 3
|
||||
opcode bits */
|
||||
static void gen_modrm(int op_reg, int r, Sym *sym, int c)
|
||||
@@ -183,13 +208,17 @@ static void gen_modrm(int op_reg, int r, Sym *sym, int c)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* load 'r' from value 'sv' */
|
||||
void load(int r, SValue *sv)
|
||||
ST_FUNC void load(int r, SValue *sv)
|
||||
{
|
||||
int v, t, ft, fc, fr;
|
||||
SValue v1;
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
SValue v2;
|
||||
sv = pe_getimport(sv, &v2);
|
||||
#endif
|
||||
|
||||
fr = sv->r;
|
||||
ft = sv->type.t;
|
||||
fc = sv->c.ul;
|
||||
@@ -200,8 +229,10 @@ void load(int r, SValue *sv)
|
||||
v1.type.t = VT_INT;
|
||||
v1.r = VT_LOCAL | VT_LVAL;
|
||||
v1.c.ul = fc;
|
||||
load(r, &v1);
|
||||
fr = r;
|
||||
if (!(reg_classes[fr] & RC_INT))
|
||||
fr = get_reg(RC_INT);
|
||||
load(fr, &v1);
|
||||
}
|
||||
if ((ft & VT_BTYPE) == VT_FLOAT) {
|
||||
o(0xd9); /* flds */
|
||||
@@ -229,8 +260,13 @@ void load(int r, SValue *sv)
|
||||
o(0xb8 + r); /* mov $xx, r */
|
||||
gen_addr32(fr, sv->sym, fc);
|
||||
} else if (v == VT_LOCAL) {
|
||||
o(0x8d); /* lea xxx(%ebp), r */
|
||||
gen_modrm(r, VT_LOCAL, sv->sym, fc);
|
||||
if (fc) {
|
||||
o(0x8d); /* lea xxx(%ebp), r */
|
||||
gen_modrm(r, VT_LOCAL, sv->sym, fc);
|
||||
} else {
|
||||
o(0x89);
|
||||
o(0xe8 + r); /* mov %ebp, r */
|
||||
}
|
||||
} else if (v == VT_CMP) {
|
||||
oad(0xb8 + r, 0); /* mov $0, r */
|
||||
o(0x0f); /* setxx %br */
|
||||
@@ -250,10 +286,15 @@ void load(int r, SValue *sv)
|
||||
}
|
||||
|
||||
/* store register 'r' in lvalue 'v' */
|
||||
void store(int r, SValue *v)
|
||||
ST_FUNC void store(int r, SValue *v)
|
||||
{
|
||||
int fr, bt, ft, fc;
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
SValue v2;
|
||||
v = pe_getimport(v, &v2);
|
||||
#endif
|
||||
|
||||
ft = v->type.t;
|
||||
fc = v->c.ul;
|
||||
fr = v->r & VT_VALMASK;
|
||||
@@ -326,7 +367,7 @@ static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX };
|
||||
/* Generate function call. The function address is pushed first, then
|
||||
all the parameters in call order. This functions pops all the
|
||||
parameters and the function address. */
|
||||
void gfunc_call(int nb_args)
|
||||
ST_FUNC void gfunc_call(int nb_args)
|
||||
{
|
||||
int size, align, r, args_size, i, func_call;
|
||||
Sym *func_sym;
|
||||
@@ -402,6 +443,11 @@ void gfunc_call(int nb_args)
|
||||
}
|
||||
}
|
||||
gcall_or_jmp(0);
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
if ((func_sym->type.t & VT_BTYPE) == VT_STRUCT)
|
||||
args_size -= 4;
|
||||
#endif
|
||||
if (args_size && func_call != FUNC_STDCALL)
|
||||
gadd_sp(args_size);
|
||||
vtop--;
|
||||
@@ -414,7 +460,7 @@ void gfunc_call(int nb_args)
|
||||
#endif
|
||||
|
||||
/* generate function prolog of type 't' */
|
||||
void gfunc_prolog(CType *func_type)
|
||||
ST_FUNC void gfunc_prolog(CType *func_type)
|
||||
{
|
||||
int addr, align, size, func_call, fastcall_nb_regs;
|
||||
int param_index, param_addr;
|
||||
@@ -426,6 +472,8 @@ void gfunc_prolog(CType *func_type)
|
||||
func_call = FUNC_CALL(sym->r);
|
||||
addr = 8;
|
||||
loc = 0;
|
||||
func_vc = 0;
|
||||
|
||||
if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
|
||||
fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
|
||||
fastcall_regs_ptr = fastcall_regs;
|
||||
@@ -478,17 +526,23 @@ void gfunc_prolog(CType *func_type)
|
||||
/* pascal type call ? */
|
||||
if (func_call == FUNC_STDCALL)
|
||||
func_ret_sub = addr - 8;
|
||||
#ifdef TCC_TARGET_PE
|
||||
else if (func_vc)
|
||||
func_ret_sub = 4;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
/* leave some room for bound checking code */
|
||||
if (tcc_state->do_bounds_check) {
|
||||
oad(0xb8, 0); /* lbound section pointer */
|
||||
oad(0xb8, 0); /* call to function */
|
||||
func_bound_offset = lbounds_section->data_offset;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* generate function epilog */
|
||||
void gfunc_epilog(void)
|
||||
ST_FUNC void gfunc_epilog(void)
|
||||
{
|
||||
int v, saved_ind;
|
||||
|
||||
@@ -559,13 +613,13 @@ void gfunc_epilog(void)
|
||||
}
|
||||
|
||||
/* generate a jump to a label */
|
||||
int gjmp(int t)
|
||||
ST_FUNC int gjmp(int t)
|
||||
{
|
||||
return psym(0xe9, t);
|
||||
}
|
||||
|
||||
/* generate a jump to a fixed address */
|
||||
void gjmp_addr(int a)
|
||||
ST_FUNC void gjmp_addr(int a)
|
||||
{
|
||||
int r;
|
||||
r = a - ind - 2;
|
||||
@@ -578,7 +632,7 @@ void gjmp_addr(int a)
|
||||
}
|
||||
|
||||
/* generate a test. set 'inv' to invert test. Stack entry is popped */
|
||||
int gtst(int inv, int t)
|
||||
ST_FUNC int gtst(int inv, int t)
|
||||
{
|
||||
int v, *p;
|
||||
|
||||
@@ -623,7 +677,7 @@ int gtst(int inv, int t)
|
||||
}
|
||||
|
||||
/* generate an integer binary operation */
|
||||
void gen_opi(int op)
|
||||
ST_FUNC void gen_opi(int op)
|
||||
{
|
||||
int r, fr, opc, c;
|
||||
|
||||
@@ -639,10 +693,16 @@ void gen_opi(int op)
|
||||
vswap();
|
||||
c = vtop->c.i;
|
||||
if (c == (char)c) {
|
||||
/* XXX: generate inc and dec for smaller code ? */
|
||||
o(0x83);
|
||||
o(0xc0 | (opc << 3) | r);
|
||||
g(c);
|
||||
/* generate inc and dec for smaller code */
|
||||
if (c==1 && opc==0) {
|
||||
o (0x40 | r); // inc
|
||||
} else if (c==1 && opc==5) {
|
||||
o (0x48 | r); // dec
|
||||
} else {
|
||||
o(0x83);
|
||||
o(0xc0 | (opc << 3) | r);
|
||||
g(c);
|
||||
}
|
||||
} else {
|
||||
o(0x81);
|
||||
oad(0xc0 | (opc << 3) | r, c);
|
||||
@@ -757,7 +817,7 @@ void gen_opi(int op)
|
||||
/* generate a floating point operation 'v = t1 op t2' instruction. The
|
||||
two operands are guaranted to have the same floating point type */
|
||||
/* XXX: need to use ST1 too */
|
||||
void gen_opf(int op)
|
||||
ST_FUNC void gen_opf(int op)
|
||||
{
|
||||
int a, ft, fc, swapped, r;
|
||||
|
||||
@@ -869,7 +929,7 @@ void gen_opf(int op)
|
||||
|
||||
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
|
||||
and 'long long' cases. */
|
||||
void gen_cvt_itof(int t)
|
||||
ST_FUNC void gen_cvt_itof(int t)
|
||||
{
|
||||
save_reg(TREG_ST0);
|
||||
gv(RC_INT);
|
||||
@@ -899,13 +959,14 @@ void gen_cvt_itof(int t)
|
||||
|
||||
/* convert fp to int 't' type */
|
||||
/* XXX: handle long long case */
|
||||
void gen_cvt_ftoi(int t)
|
||||
ST_FUNC void gen_cvt_ftoi(int t)
|
||||
{
|
||||
int r, r2, size;
|
||||
Sym *sym;
|
||||
CType ushort_type;
|
||||
|
||||
ushort_type.t = VT_SHORT | VT_UNSIGNED;
|
||||
ushort_type.ref = 0;
|
||||
|
||||
gv(RC_FLOAT);
|
||||
if (t != VT_INT)
|
||||
@@ -949,14 +1010,14 @@ void gen_cvt_ftoi(int t)
|
||||
}
|
||||
|
||||
/* convert from one floating point type to another */
|
||||
void gen_cvt_ftof(int t)
|
||||
ST_FUNC void gen_cvt_ftof(int t)
|
||||
{
|
||||
/* all we have to do on i386 is to put the float in a register */
|
||||
gv(RC_FLOAT);
|
||||
}
|
||||
|
||||
/* computed goto support */
|
||||
void ggoto(void)
|
||||
ST_FUNC void ggoto(void)
|
||||
{
|
||||
gcall_or_jmp(1);
|
||||
vtop--;
|
||||
@@ -966,7 +1027,7 @@ void ggoto(void)
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
|
||||
/* generate a bounded pointer addition */
|
||||
void gen_bounded_ptr_add(void)
|
||||
ST_FUNC void gen_bounded_ptr_add(void)
|
||||
{
|
||||
Sym *sym;
|
||||
|
||||
@@ -989,7 +1050,7 @@ void gen_bounded_ptr_add(void)
|
||||
|
||||
/* patch pointer addition in vtop so that pointer dereferencing is
|
||||
also tested */
|
||||
void gen_bounded_ptr_deref(void)
|
||||
ST_FUNC void gen_bounded_ptr_deref(void)
|
||||
{
|
||||
int func;
|
||||
int size, align;
|
||||
@@ -1014,7 +1075,7 @@ void gen_bounded_ptr_deref(void)
|
||||
case 12: func = TOK___bound_ptr_indir12; break;
|
||||
case 16: func = TOK___bound_ptr_indir16; break;
|
||||
default:
|
||||
error("unhandled size when derefencing bounded pointer");
|
||||
tcc_error("unhandled size when dereferencing bounded pointer");
|
||||
func = 0;
|
||||
break;
|
||||
}
|
||||
@@ -1031,4 +1092,5 @@ void gen_bounded_ptr_deref(void)
|
||||
|
||||
/* end of X86 code generator */
|
||||
/*************************************************************/
|
||||
|
||||
#endif
|
||||
/*************************************************************/
|
||||
|
||||
243
i386-tok.h
Normal file
243
i386-tok.h
Normal file
@@ -0,0 +1,243 @@
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* WARNING: relative order of tokens is important. */
|
||||
|
||||
/* register */
|
||||
DEF_ASM(al)
|
||||
DEF_ASM(cl)
|
||||
DEF_ASM(dl)
|
||||
DEF_ASM(bl)
|
||||
DEF_ASM(ah)
|
||||
DEF_ASM(ch)
|
||||
DEF_ASM(dh)
|
||||
DEF_ASM(bh)
|
||||
DEF_ASM(ax)
|
||||
DEF_ASM(cx)
|
||||
DEF_ASM(dx)
|
||||
DEF_ASM(bx)
|
||||
DEF_ASM(sp)
|
||||
DEF_ASM(bp)
|
||||
DEF_ASM(si)
|
||||
DEF_ASM(di)
|
||||
DEF_ASM(eax)
|
||||
DEF_ASM(ecx)
|
||||
DEF_ASM(edx)
|
||||
DEF_ASM(ebx)
|
||||
DEF_ASM(esp)
|
||||
DEF_ASM(ebp)
|
||||
DEF_ASM(esi)
|
||||
DEF_ASM(edi)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
DEF_ASM(rax)
|
||||
DEF_ASM(rcx)
|
||||
DEF_ASM(rdx)
|
||||
DEF_ASM(rbx)
|
||||
DEF_ASM(rsp)
|
||||
DEF_ASM(rbp)
|
||||
DEF_ASM(rsi)
|
||||
DEF_ASM(rdi)
|
||||
#endif
|
||||
DEF_ASM(mm0)
|
||||
DEF_ASM(mm1)
|
||||
DEF_ASM(mm2)
|
||||
DEF_ASM(mm3)
|
||||
DEF_ASM(mm4)
|
||||
DEF_ASM(mm5)
|
||||
DEF_ASM(mm6)
|
||||
DEF_ASM(mm7)
|
||||
DEF_ASM(xmm0)
|
||||
DEF_ASM(xmm1)
|
||||
DEF_ASM(xmm2)
|
||||
DEF_ASM(xmm3)
|
||||
DEF_ASM(xmm4)
|
||||
DEF_ASM(xmm5)
|
||||
DEF_ASM(xmm6)
|
||||
DEF_ASM(xmm7)
|
||||
DEF_ASM(cr0)
|
||||
DEF_ASM(cr1)
|
||||
DEF_ASM(cr2)
|
||||
DEF_ASM(cr3)
|
||||
DEF_ASM(cr4)
|
||||
DEF_ASM(cr5)
|
||||
DEF_ASM(cr6)
|
||||
DEF_ASM(cr7)
|
||||
DEF_ASM(tr0)
|
||||
DEF_ASM(tr1)
|
||||
DEF_ASM(tr2)
|
||||
DEF_ASM(tr3)
|
||||
DEF_ASM(tr4)
|
||||
DEF_ASM(tr5)
|
||||
DEF_ASM(tr6)
|
||||
DEF_ASM(tr7)
|
||||
DEF_ASM(db0)
|
||||
DEF_ASM(db1)
|
||||
DEF_ASM(db2)
|
||||
DEF_ASM(db3)
|
||||
DEF_ASM(db4)
|
||||
DEF_ASM(db5)
|
||||
DEF_ASM(db6)
|
||||
DEF_ASM(db7)
|
||||
DEF_ASM(dr0)
|
||||
DEF_ASM(dr1)
|
||||
DEF_ASM(dr2)
|
||||
DEF_ASM(dr3)
|
||||
DEF_ASM(dr4)
|
||||
DEF_ASM(dr5)
|
||||
DEF_ASM(dr6)
|
||||
DEF_ASM(dr7)
|
||||
DEF_ASM(es)
|
||||
DEF_ASM(cs)
|
||||
DEF_ASM(ss)
|
||||
DEF_ASM(ds)
|
||||
DEF_ASM(fs)
|
||||
DEF_ASM(gs)
|
||||
DEF_ASM(st)
|
||||
|
||||
/* generic two operands */
|
||||
DEF_BWLX(mov)
|
||||
|
||||
DEF_BWLX(add)
|
||||
DEF_BWLX(or)
|
||||
DEF_BWLX(adc)
|
||||
DEF_BWLX(sbb)
|
||||
DEF_BWLX(and)
|
||||
DEF_BWLX(sub)
|
||||
DEF_BWLX(xor)
|
||||
DEF_BWLX(cmp)
|
||||
|
||||
/* unary ops */
|
||||
DEF_BWLX(inc)
|
||||
DEF_BWLX(dec)
|
||||
DEF_BWLX(not)
|
||||
DEF_BWLX(neg)
|
||||
DEF_BWLX(mul)
|
||||
DEF_BWLX(imul)
|
||||
DEF_BWLX(div)
|
||||
DEF_BWLX(idiv)
|
||||
|
||||
DEF_BWLX(xchg)
|
||||
DEF_BWLX(test)
|
||||
|
||||
/* shifts */
|
||||
DEF_BWLX(rol)
|
||||
DEF_BWLX(ror)
|
||||
DEF_BWLX(rcl)
|
||||
DEF_BWLX(rcr)
|
||||
DEF_BWLX(shl)
|
||||
DEF_BWLX(shr)
|
||||
DEF_BWLX(sar)
|
||||
|
||||
DEF_ASM(shldw)
|
||||
DEF_ASM(shldl)
|
||||
DEF_ASM(shld)
|
||||
DEF_ASM(shrdw)
|
||||
DEF_ASM(shrdl)
|
||||
DEF_ASM(shrd)
|
||||
|
||||
DEF_ASM(pushw)
|
||||
DEF_ASM(pushl)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
DEF_ASM(pushq)
|
||||
#endif
|
||||
DEF_ASM(push)
|
||||
|
||||
DEF_ASM(popw)
|
||||
DEF_ASM(popl)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
DEF_ASM(popq)
|
||||
#endif
|
||||
DEF_ASM(pop)
|
||||
|
||||
DEF_BWL(in)
|
||||
DEF_BWL(out)
|
||||
|
||||
DEF_WL(movzb)
|
||||
DEF_ASM(movzwl)
|
||||
DEF_ASM(movsbw)
|
||||
DEF_ASM(movsbl)
|
||||
DEF_ASM(movswl)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
DEF_ASM(movslq)
|
||||
#endif
|
||||
|
||||
DEF_WLX(lea)
|
||||
|
||||
DEF_ASM(les)
|
||||
DEF_ASM(lds)
|
||||
DEF_ASM(lss)
|
||||
DEF_ASM(lfs)
|
||||
DEF_ASM(lgs)
|
||||
|
||||
DEF_ASM(call)
|
||||
DEF_ASM(jmp)
|
||||
DEF_ASM(lcall)
|
||||
DEF_ASM(ljmp)
|
||||
|
||||
DEF_ASMTEST(j)
|
||||
|
||||
DEF_ASMTEST(set)
|
||||
DEF_ASMTEST(cmov)
|
||||
|
||||
DEF_WLX(bsf)
|
||||
DEF_WLX(bsr)
|
||||
DEF_WLX(bt)
|
||||
DEF_WLX(bts)
|
||||
DEF_WLX(btr)
|
||||
DEF_WLX(btc)
|
||||
|
||||
DEF_WLX(lsl)
|
||||
|
||||
/* generic FP ops */
|
||||
DEF_FP(add)
|
||||
DEF_FP(mul)
|
||||
|
||||
DEF_ASM(fcom)
|
||||
DEF_ASM(fcom_1) /* non existant op, just to have a regular table */
|
||||
DEF_FP1(com)
|
||||
|
||||
DEF_FP(comp)
|
||||
DEF_FP(sub)
|
||||
DEF_FP(subr)
|
||||
DEF_FP(div)
|
||||
DEF_FP(divr)
|
||||
|
||||
DEF_BWLX(xadd)
|
||||
DEF_BWLX(cmpxchg)
|
||||
|
||||
/* string ops */
|
||||
DEF_BWLX(cmps)
|
||||
DEF_BWLX(scmp)
|
||||
DEF_BWL(ins)
|
||||
DEF_BWL(outs)
|
||||
DEF_BWLX(lods)
|
||||
DEF_BWLX(slod)
|
||||
DEF_BWLX(movs)
|
||||
DEF_BWLX(smov)
|
||||
DEF_BWLX(scas)
|
||||
DEF_BWLX(ssca)
|
||||
DEF_BWLX(stos)
|
||||
DEF_BWLX(ssto)
|
||||
|
||||
/* generic asm ops */
|
||||
#define ALT(x)
|
||||
#define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
|
||||
#define DEF_ASM_OP0L(name, opcode, group, instr_type)
|
||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
# include "x86_64-asm.h"
|
||||
#else
|
||||
# include "i386-asm.h"
|
||||
#endif
|
||||
|
||||
#define ALT(x)
|
||||
#define DEF_ASM_OP0(name, opcode)
|
||||
#define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
|
||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
# include "x86_64-asm.h"
|
||||
#else
|
||||
# include "i386-asm.h"
|
||||
#endif
|
||||
6
il-gen.c
6
il-gen.c
@@ -41,7 +41,7 @@ enum {
|
||||
REG_ST2,
|
||||
};
|
||||
|
||||
int reg_classes[NB_REGS] = {
|
||||
const int reg_classes[NB_REGS] = {
|
||||
/* ST0 */ RC_ST | RC_ST0,
|
||||
/* ST1 */ RC_ST | RC_ST1,
|
||||
/* ST2 */ RC_ST,
|
||||
@@ -193,7 +193,7 @@ static void il_type_to_str(char *buf, int buf_size,
|
||||
pstrcat(buf, buf_size, tstr);
|
||||
break;
|
||||
case VT_STRUCT:
|
||||
error("structures not handled yet");
|
||||
tcc_error("structures not handled yet");
|
||||
break;
|
||||
case VT_FUNC:
|
||||
s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
|
||||
@@ -387,7 +387,7 @@ void gfunc_start(GFuncContext *c, int func_call)
|
||||
void gfunc_param(GFuncContext *c)
|
||||
{
|
||||
if ((vtop->t & VT_BTYPE) == VT_STRUCT) {
|
||||
error("structures passed as value not handled yet");
|
||||
tcc_error("structures passed as value not handled yet");
|
||||
} else {
|
||||
/* simply push on stack */
|
||||
gv(RC_ST0);
|
||||
|
||||
@@ -2,62 +2,36 @@
|
||||
#define _STDARG_H
|
||||
|
||||
#ifdef __x86_64__
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN64
|
||||
|
||||
/* GCC compatible definition of va_list. */
|
||||
struct __va_list_struct {
|
||||
unsigned int gp_offset;
|
||||
unsigned int fp_offset;
|
||||
union {
|
||||
unsigned int overflow_offset;
|
||||
char *overflow_arg_area;
|
||||
};
|
||||
char *reg_save_area;
|
||||
};
|
||||
typedef void *va_list;
|
||||
|
||||
typedef struct __va_list_struct *va_list;
|
||||
va_list __va_start(void *fp);
|
||||
void *__va_arg(va_list ap, int arg_type, int size);
|
||||
va_list __va_copy(va_list src);
|
||||
void __va_end(va_list ap);
|
||||
|
||||
/* we use __builtin_(malloc|free) to avoid #define malloc tcc_malloc */
|
||||
/* XXX: this lacks the support of aggregated types. */
|
||||
#define va_start(ap, last) \
|
||||
(ap = (va_list)__builtin_malloc(sizeof(struct __va_list_struct)), \
|
||||
*ap = *(struct __va_list_struct*)( \
|
||||
(char*)__builtin_frame_address(0) - 16), \
|
||||
ap->overflow_arg_area = ((char *)__builtin_frame_address(0) + \
|
||||
ap->overflow_offset), \
|
||||
ap->reg_save_area = (char *)__builtin_frame_address(0) - 176 - 16 \
|
||||
)
|
||||
#define va_arg(ap, type) \
|
||||
(*(type*)(__builtin_types_compatible_p(type, long double) \
|
||||
? (ap->overflow_arg_area += 16, \
|
||||
ap->overflow_arg_area - 16) \
|
||||
: __builtin_types_compatible_p(type, double) \
|
||||
? (ap->fp_offset < 128 + 48 \
|
||||
? (ap->fp_offset += 16, \
|
||||
ap->reg_save_area + ap->fp_offset - 16) \
|
||||
: (ap->overflow_arg_area += 8, \
|
||||
ap->overflow_arg_area - 8)) \
|
||||
: (ap->gp_offset < 48 \
|
||||
? (ap->gp_offset += 8, \
|
||||
ap->reg_save_area + ap->gp_offset - 8) \
|
||||
: (ap->overflow_arg_area += 8, \
|
||||
ap->overflow_arg_area - 8)) \
|
||||
))
|
||||
#define va_copy(dest, src) \
|
||||
((dest) = (va_list)malloc(sizeof(struct __va_list_struct)), \
|
||||
*(dest) = *(src))
|
||||
#define va_end(ap) __builtin_free(ap)
|
||||
|
||||
#else
|
||||
#define va_start(ap, last) ((ap) = __va_start(__builtin_frame_address(0)))
|
||||
#define va_arg(ap, type) \
|
||||
(*(type *)(__va_arg(ap, __builtin_va_arg_types(type), sizeof(type))))
|
||||
#define va_copy(dest, src) ((dest) = __va_copy(src))
|
||||
#define va_end(ap) __va_end(ap)
|
||||
|
||||
#else /* _WIN64 */
|
||||
typedef char *va_list;
|
||||
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+7)&~7)
|
||||
#define va_arg(ap,type) (ap += (sizeof(type)+7)&~7, *(type *)(ap - ((sizeof(type)+7)&~7)))
|
||||
#define va_copy(dest, src) (dest) = (src)
|
||||
#define va_end(ap)
|
||||
#endif
|
||||
|
||||
#else /* __i386__ */
|
||||
typedef char *va_list;
|
||||
/* only correct for i386 */
|
||||
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
|
||||
#define va_arg(ap,type) (ap += (sizeof(type)+3)&~3, *(type *)(ap - ((sizeof(type)+3)&~3)))
|
||||
#define va_copy(dest, src) (dest) = (src)
|
||||
#define va_end(ap)
|
||||
|
||||
#endif
|
||||
|
||||
/* fix a buggy dependency on GCC in libio.h */
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
#ifndef _STDDEF_H
|
||||
#define _STDDEF_H
|
||||
|
||||
#define NULL ((void *)0)
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __PTRDIFF_TYPE__ ssize_t;
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||
#define offsetof(type, field) ((size_t) &((type *)0)->field)
|
||||
typedef __PTRDIFF_TYPE__ intptr_t;
|
||||
typedef __SIZE_TYPE__ uintptr_t;
|
||||
|
||||
#ifndef __int8_t_defined
|
||||
#define __int8_t_defined
|
||||
typedef char int8_t;
|
||||
typedef short int int16_t;
|
||||
typedef int int32_t;
|
||||
typedef long long int int64_t;
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef signed long long int int64_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short int uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long int uint64_t;
|
||||
#endif
|
||||
|
||||
#define NULL ((void*)0)
|
||||
#define offsetof(type, field) ((size_t)&((type *)0)->field)
|
||||
|
||||
void *alloca(size_t size);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* This file has no copyright assigned and is placed in the Public Domain.
|
||||
* This file is part of the w64 mingw-runtime package.
|
||||
* No warranty is given; refer to the file DISCLAIMER within this package.
|
||||
*/
|
||||
#ifndef _VARARGS_H
|
||||
#define _VARARGS_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#define va_dcl
|
||||
#define va_alist __va_alist
|
||||
#undef va_start
|
||||
#define va_start(ap) ap = __builtin_varargs_start
|
||||
#error "TinyCC no longer implements <varargs.h>."
|
||||
#error "Revise your code to use <stdarg.h>."
|
||||
|
||||
#endif
|
||||
|
||||
102
lib/Makefile
Normal file
102
lib/Makefile
Normal file
@@ -0,0 +1,102 @@
|
||||
#
|
||||
# Tiny C Compiler Makefile for libtcc1.a
|
||||
#
|
||||
|
||||
TOP = ..
|
||||
include $(TOP)/Makefile
|
||||
VPATH = $(top_srcdir)/lib $(top_srcdir)/win32/lib
|
||||
|
||||
ifndef TARGET
|
||||
ifdef CONFIG_WIN64
|
||||
TARGET = x86_64-win32
|
||||
else
|
||||
ifdef CONFIG_WIN32
|
||||
TARGET = i386-win32
|
||||
else
|
||||
ifeq ($(ARCH),i386)
|
||||
TARGET = i386
|
||||
ifneq ($(TARGETOS),Darwin)
|
||||
XCC = $(CC)
|
||||
endif
|
||||
else
|
||||
ifeq ($(ARCH),x86-64)
|
||||
TARGET = x86_64
|
||||
ifneq ($(TARGETOS),Darwin)
|
||||
XCC = $(CC)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
BCHECK_O = bcheck.o
|
||||
endif
|
||||
|
||||
DIR = $(TARGET)
|
||||
|
||||
native : ../libtcc1.a
|
||||
cross : $(DIR)/libtcc1.a
|
||||
|
||||
native : TCC = $(TOP)/tcc$(EXESUF)
|
||||
cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)
|
||||
|
||||
I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O)
|
||||
X86_64_O = libtcc1.o alloca86_64.o
|
||||
WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
|
||||
WIN64_O = $(X86_64_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
|
||||
|
||||
ifeq "$(TARGET)" "i386-win32"
|
||||
OBJ = $(addprefix $(DIR)/,$(WIN32_O))
|
||||
TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE
|
||||
XCC = $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include
|
||||
XAR = $(DIR)/tiny_libmaker$(EXESUF)
|
||||
else
|
||||
ifeq "$(TARGET)" "x86_64-win32"
|
||||
OBJ = $(addprefix $(DIR)/,$(WIN64_O))
|
||||
TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE
|
||||
XCC = $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include
|
||||
XAR = $(DIR)/tiny_libmaker$(EXESUF)
|
||||
else
|
||||
ifeq "$(TARGET)" "i386"
|
||||
OBJ = $(addprefix $(DIR)/,$(I386_O))
|
||||
TGT = -DTCC_TARGET_I386
|
||||
XCC ?= $(TCC) -B$(TOP)
|
||||
else
|
||||
ifeq "$(TARGET)" "x86_64"
|
||||
OBJ = $(addprefix $(DIR)/,$(X86_64_O))
|
||||
TGT = -DTCC_TARGET_X86_64
|
||||
XCC ?= $(TCC) -B$(TOP)
|
||||
else
|
||||
$(error libtcc1.a not supported on target '$(TARGET)')
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
XFLAGS = $(CPPFLAGS) $(CFLAGS) $(TGT)
|
||||
|
||||
ifeq ($(TARGETOS),Darwin)
|
||||
XAR = $(DIR)/tiny_libmaker$(EXESUF)
|
||||
XFLAGS += -D_ANSI_SOURCE
|
||||
BCHECK_O =
|
||||
endif
|
||||
|
||||
ifdef XAR
|
||||
AR = $(XAR)
|
||||
endif
|
||||
|
||||
$(DIR)/libtcc1.a ../libtcc1.a : $(OBJ) $(XAR)
|
||||
$(AR) rcs $@ $(OBJ)
|
||||
$(DIR)/%.o : %.c
|
||||
$(XCC) -c $< -o $@ $(XFLAGS)
|
||||
$(DIR)/%.o : %.S
|
||||
$(XCC) -c $< -o $@ $(XFLAGS)
|
||||
$(DIR)/%$(EXESUF) : $(TOP)/win32/tools/%.c
|
||||
$(CC) -o $@ $< $(XFLAGS) $(LDFLAGS)
|
||||
|
||||
$(OBJ) $(XAR) : $(DIR)/exists
|
||||
$(DIR)/exists :
|
||||
mkdir -p $(DIR)
|
||||
@echo $@ > $@
|
||||
|
||||
clean :
|
||||
rm -rfv i386-win32 x86_64-win32 i386 x86_64
|
||||
@@ -1,7 +1,5 @@
|
||||
/* ---------------------------------------------- */
|
||||
/* alloca86b.S */
|
||||
|
||||
#include "../config.h"
|
||||
/* alloca86-bt.S */
|
||||
|
||||
.globl __bound_alloca
|
||||
|
||||
@@ -42,4 +40,8 @@ p6:
|
||||
push %edx
|
||||
ret
|
||||
|
||||
/* mark stack as nonexecutable */
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
/* ---------------------------------------------- */
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/* ---------------------------------------------- */
|
||||
/* alloca86.S */
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
.globl alloca
|
||||
|
||||
alloca:
|
||||
@@ -30,4 +28,8 @@ p3:
|
||||
push %edx
|
||||
ret
|
||||
|
||||
/* mark stack as nonexecutable */
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
/* ---------------------------------------------- */
|
||||
|
||||
42
lib/alloca86_64.S
Normal file
42
lib/alloca86_64.S
Normal file
@@ -0,0 +1,42 @@
|
||||
/* ---------------------------------------------- */
|
||||
/* alloca86_64.S */
|
||||
|
||||
.globl alloca
|
||||
|
||||
alloca:
|
||||
pop %rdx
|
||||
#ifdef TCC_TARGET_PE
|
||||
mov %rcx,%rax
|
||||
#else
|
||||
mov %rdi,%rax
|
||||
#endif
|
||||
add $15,%rax
|
||||
and $-16,%rax
|
||||
jz p3
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
p1:
|
||||
cmp $4096,%rax
|
||||
jle p2
|
||||
sub $4096,%rsp
|
||||
sub $4096,%rax
|
||||
test %rax,(%rsp)
|
||||
jmp p1
|
||||
p2:
|
||||
#endif
|
||||
|
||||
sub %rax,%rsp
|
||||
mov %rsp,%rax
|
||||
#ifdef TCC_TARGET_PE
|
||||
add $32,%rax
|
||||
#endif
|
||||
|
||||
p3:
|
||||
push %rdx
|
||||
ret
|
||||
|
||||
/* mark stack as nonexecutable */
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
/* ---------------------------------------------- */
|
||||
109
lib/bcheck.c
109
lib/bcheck.c
@@ -21,9 +21,13 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#if !defined(__FreeBSD__) && !defined(__DragonFly__) && !defined(__OpenBSD__)
|
||||
#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) \
|
||||
&& !defined(__DragonFly__) && !defined(__OpenBSD__)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#if !defined(_WIN32)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
//#define BOUND_DEBUG
|
||||
|
||||
@@ -33,12 +37,13 @@
|
||||
|
||||
/* use malloc hooks. Currently the code cannot be reliable if no hooks */
|
||||
#define CONFIG_TCC_MALLOC_HOOKS
|
||||
|
||||
#define HAVE_MEMALIGN
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__dietlibc__) \
|
||||
|| defined(__UCLIBC__) || defined(__OpenBSD__)
|
||||
#warning Bound checking not fully supported in this environment.
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
|
||||
|| defined(__DragonFly__) || defined(__dietlibc__) \
|
||||
|| defined(__UCLIBC__) || defined(__OpenBSD__) \
|
||||
|| defined(_WIN32) || defined(TCC_UCLIBC)
|
||||
#warning Bound checking does not support malloc (etc.) in this environment.
|
||||
#undef CONFIG_TCC_MALLOC_HOOKS
|
||||
#undef HAVE_MEMALIGN
|
||||
#endif
|
||||
@@ -93,9 +98,6 @@ static void *saved_realloc_hook;
|
||||
static void *saved_memalign_hook;
|
||||
#endif
|
||||
|
||||
/* linker definitions */
|
||||
extern char _end;
|
||||
|
||||
/* TCC definitions */
|
||||
extern char __bounds_start; /* start of static bounds table */
|
||||
/* error message, just for TCC */
|
||||
@@ -152,9 +154,6 @@ static void bound_alloc_error(void)
|
||||
bound_error("not enough memory for bound checking code");
|
||||
}
|
||||
|
||||
/* currently, tcc cannot compile that because we use GNUC extensions */
|
||||
#if !defined(__TINYC__)
|
||||
|
||||
/* return '(p + offset)' for pointer arithmetic (a pointer can reach
|
||||
the end of a region in this case */
|
||||
void * FASTCALL __bound_ptr_add(void *p, int offset)
|
||||
@@ -203,17 +202,18 @@ void * FASTCALL __bound_ptr_indir ## dsize (void *p, int offset) \
|
||||
return p + offset; \
|
||||
}
|
||||
|
||||
#ifdef __i386__
|
||||
BOUND_PTR_INDIR(1)
|
||||
BOUND_PTR_INDIR(2)
|
||||
BOUND_PTR_INDIR(4)
|
||||
BOUND_PTR_INDIR(8)
|
||||
BOUND_PTR_INDIR(12)
|
||||
BOUND_PTR_INDIR(16)
|
||||
|
||||
/* return the frame pointer of the caller */
|
||||
#define GET_CALLER_FP(fp)\
|
||||
{\
|
||||
unsigned long *fp1;\
|
||||
__asm__ __volatile__ ("movl %%ebp,%0" :"=g" (fp1));\
|
||||
fp = fp1[0];\
|
||||
fp = (unsigned long)__builtin_frame_address(1);\
|
||||
}
|
||||
#else
|
||||
#error put code to extract the calling frame pointer
|
||||
#endif
|
||||
|
||||
/* called when entering a function to add all the local regions */
|
||||
void FASTCALL __bound_local_new(void *p1)
|
||||
@@ -246,34 +246,6 @@ void FASTCALL __bound_local_delete(void *p1)
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void __bound_local_new(void *p)
|
||||
{
|
||||
}
|
||||
void __bound_local_delete(void *p)
|
||||
{
|
||||
}
|
||||
|
||||
void *__bound_ptr_add(void *p, int offset)
|
||||
{
|
||||
return p + offset;
|
||||
}
|
||||
|
||||
#define BOUND_PTR_INDIR(dsize) \
|
||||
void *__bound_ptr_indir ## dsize (void *p, int offset) \
|
||||
{ \
|
||||
return p + offset; \
|
||||
}
|
||||
#endif
|
||||
|
||||
BOUND_PTR_INDIR(1)
|
||||
BOUND_PTR_INDIR(2)
|
||||
BOUND_PTR_INDIR(4)
|
||||
BOUND_PTR_INDIR(8)
|
||||
BOUND_PTR_INDIR(12)
|
||||
BOUND_PTR_INDIR(16)
|
||||
|
||||
static BoundEntry *__bound_new_page(void)
|
||||
{
|
||||
BoundEntry *page;
|
||||
@@ -406,11 +378,34 @@ void __bound_init(void)
|
||||
size = BOUND_T23_SIZE;
|
||||
mark_invalid(start, size);
|
||||
|
||||
#if !defined(__TINYC__) && defined(CONFIG_TCC_MALLOC_HOOKS)
|
||||
#if defined(CONFIG_TCC_MALLOC_HOOKS)
|
||||
/* malloc zone is also marked invalid. can only use that with
|
||||
hooks because all libs should use the same malloc. The solution
|
||||
would be to build a new malloc for tcc. */
|
||||
start = (unsigned long)&_end;
|
||||
* hooks because all libs should use the same malloc. The solution
|
||||
* would be to build a new malloc for tcc.
|
||||
*
|
||||
* usually heap (= malloc zone) comes right after bss, i.e. after _end, but
|
||||
* not always - either if we are running from under `tcc -b -run`, or if
|
||||
* address space randomization is turned on(a), heap start will be separated
|
||||
* from bss end.
|
||||
*
|
||||
* So sbrk(0) will be a good approximation for start_brk:
|
||||
*
|
||||
* - if we are a separately compiled program, __bound_init() runs early,
|
||||
* and sbrk(0) should be equal or very near to start_brk(b) (in case other
|
||||
* constructors malloc something), or
|
||||
*
|
||||
* - if we are running from under `tcc -b -run`, sbrk(0) will return
|
||||
* start of heap portion which is under this program control, and not
|
||||
* mark as invalid earlier allocated memory.
|
||||
*
|
||||
*
|
||||
* (a) /proc/sys/kernel/randomize_va_space = 2, on Linux;
|
||||
* usually turned on by default.
|
||||
*
|
||||
* (b) on Linux >= v3.3, the alternative is to read
|
||||
* start_brk from /proc/self/stat
|
||||
*/
|
||||
start = (unsigned long)sbrk(0);
|
||||
size = 128 * 0x100000;
|
||||
mark_invalid(start, size);
|
||||
#endif
|
||||
@@ -423,6 +418,11 @@ void __bound_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
void __bound_exit(void)
|
||||
{
|
||||
restore_malloc_hooks();
|
||||
}
|
||||
|
||||
static inline void add_region(BoundEntry *e,
|
||||
unsigned long start, unsigned long size)
|
||||
{
|
||||
@@ -616,7 +616,7 @@ int __bound_delete_region(void *p)
|
||||
}
|
||||
}
|
||||
/* last page */
|
||||
page = get_page(t2_end);
|
||||
page = get_page(t1_end);
|
||||
e2 = (BoundEntry *)((char *)page + t2_end);
|
||||
for(e=page;e<e2;e++) {
|
||||
e->start = 0;
|
||||
@@ -648,6 +648,9 @@ static unsigned long get_region_size(void *p)
|
||||
|
||||
/* patched memory functions */
|
||||
|
||||
/* force compiler to perform stores coded up to this point */
|
||||
#define barrier() __asm__ __volatile__ ("": : : "memory")
|
||||
|
||||
static void install_malloc_hooks(void)
|
||||
{
|
||||
#ifdef CONFIG_TCC_MALLOC_HOOKS
|
||||
@@ -659,6 +662,8 @@ static void install_malloc_hooks(void)
|
||||
__free_hook = __bound_free;
|
||||
__realloc_hook = __bound_realloc;
|
||||
__memalign_hook = __bound_memalign;
|
||||
|
||||
barrier();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -669,6 +674,8 @@ static void restore_malloc_hooks(void)
|
||||
__free_hook = saved_free_hook;
|
||||
__realloc_hook = saved_realloc_hook;
|
||||
__memalign_hook = saved_memalign_hook;
|
||||
|
||||
barrier();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ static UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
|
||||
n0 = nn.s.low;
|
||||
n1 = nn.s.high;
|
||||
|
||||
#if !UDIV_NEEDS_NORMALIZATION
|
||||
#if !defined(UDIV_NEEDS_NORMALIZATION)
|
||||
if (d1 == 0)
|
||||
{
|
||||
if (d0 > n1)
|
||||
@@ -605,3 +605,87 @@ unsigned long long __fixunsxfdi (long double a1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__) && !defined(_WIN64)
|
||||
|
||||
/* helper functions for stdarg.h */
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifndef __TINYC__
|
||||
/* gives "incompatible types for redefinition of __va_arg" below */
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
enum __va_arg_type {
|
||||
__va_gen_reg, __va_float_reg, __va_stack
|
||||
};
|
||||
|
||||
/* GCC compatible definition of va_list. */
|
||||
struct __va_list_struct {
|
||||
unsigned int gp_offset;
|
||||
unsigned int fp_offset;
|
||||
union {
|
||||
unsigned int overflow_offset;
|
||||
char *overflow_arg_area;
|
||||
};
|
||||
char *reg_save_area;
|
||||
};
|
||||
|
||||
void *__va_start(void *fp)
|
||||
{
|
||||
struct __va_list_struct *ap =
|
||||
(struct __va_list_struct *)malloc(sizeof(struct __va_list_struct));
|
||||
*ap = *(struct __va_list_struct *)((char *)fp - 16);
|
||||
ap->overflow_arg_area = (char *)fp + ap->overflow_offset;
|
||||
ap->reg_save_area = (char *)fp - 176 - 16;
|
||||
return ap;
|
||||
}
|
||||
|
||||
void *__va_arg(struct __va_list_struct *ap,
|
||||
enum __va_arg_type arg_type,
|
||||
int size)
|
||||
{
|
||||
size = (size + 7) & ~7;
|
||||
switch (arg_type) {
|
||||
case __va_gen_reg:
|
||||
if (ap->gp_offset < 48) {
|
||||
ap->gp_offset += 8;
|
||||
return ap->reg_save_area + ap->gp_offset - 8;
|
||||
}
|
||||
size = 8;
|
||||
goto use_overflow_area;
|
||||
|
||||
case __va_float_reg:
|
||||
if (ap->fp_offset < 128 + 48) {
|
||||
ap->fp_offset += 16;
|
||||
return ap->reg_save_area + ap->fp_offset - 16;
|
||||
}
|
||||
size = 8;
|
||||
goto use_overflow_area;
|
||||
|
||||
case __va_stack:
|
||||
use_overflow_area:
|
||||
ap->overflow_arg_area += size;
|
||||
return ap->overflow_arg_area - size;
|
||||
|
||||
default:
|
||||
#ifndef __TINYC__
|
||||
fprintf(stderr, "unknown ABI type for __va_arg\n");
|
||||
#endif
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void *__va_copy(struct __va_list_struct *src)
|
||||
{
|
||||
struct __va_list_struct *dest =
|
||||
(struct __va_list_struct *)malloc(sizeof(struct __va_list_struct));
|
||||
*dest = *src;
|
||||
return dest;
|
||||
}
|
||||
|
||||
void __va_end(struct __va_list_struct *ap)
|
||||
{
|
||||
free(ap);
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
||||
48
libtcc.h
48
libtcc.h
@@ -1,10 +1,8 @@
|
||||
#ifndef LIBTCC_H
|
||||
#define LIBTCC_H
|
||||
|
||||
#ifdef LIBTCC_AS_DLL
|
||||
#define LIBTCCAPI __declspec(dllexport)
|
||||
#else
|
||||
#define LIBTCCAPI
|
||||
#ifndef LIBTCCAPI
|
||||
# define LIBTCCAPI
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -21,15 +19,15 @@ LIBTCCAPI TCCState *tcc_new(void);
|
||||
/* free a TCC compilation context */
|
||||
LIBTCCAPI void tcc_delete(TCCState *s);
|
||||
|
||||
/* add debug information in the generated code */
|
||||
LIBTCCAPI void tcc_enable_debug(TCCState *s);
|
||||
/* set CONFIG_TCCDIR at runtime */
|
||||
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
|
||||
|
||||
/* set error/warning display callback */
|
||||
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque,
|
||||
void (*error_func)(void *opaque, const char *msg));
|
||||
void (*error_func)(void *opaque, const char *msg));
|
||||
|
||||
/* set/reset a warning */
|
||||
LIBTCCAPI int tcc_set_warning(TCCState *s, const char *warning_name, int value);
|
||||
/* set options as from command line (multiple supported) */
|
||||
LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);
|
||||
|
||||
/*****************************/
|
||||
/* preprocessor */
|
||||
@@ -49,29 +47,22 @@ LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym);
|
||||
/*****************************/
|
||||
/* compiling */
|
||||
|
||||
/* add a file (either a C file, dll, an object, a library or an ld
|
||||
script). Return -1 if error. */
|
||||
/* add a file (C file, dll, object, library, ld script). Return -1 if error. */
|
||||
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename);
|
||||
|
||||
/* compile a string containing a C source. Return non zero if
|
||||
error. */
|
||||
/* compile a string containing a C source. Return -1 if error. */
|
||||
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
|
||||
|
||||
/*****************************/
|
||||
/* linking commands */
|
||||
|
||||
/* set output type. MUST BE CALLED before any compilation */
|
||||
#define TCC_OUTPUT_MEMORY 0 /* output will be ran in memory (no
|
||||
output file) (default) */
|
||||
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
|
||||
#define TCC_OUTPUT_MEMORY 0 /* output will be run in memory (default) */
|
||||
#define TCC_OUTPUT_EXE 1 /* executable file */
|
||||
#define TCC_OUTPUT_DLL 2 /* dynamic library */
|
||||
#define TCC_OUTPUT_OBJ 3 /* object file */
|
||||
#define TCC_OUTPUT_PREPROCESS 4 /* preprocessed file (used internally) */
|
||||
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
|
||||
|
||||
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
|
||||
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
|
||||
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
|
||||
#define TCC_OUTPUT_PREPROCESS 4 /* only preprocess (used internally) */
|
||||
|
||||
/* equivalent to -Lpath option */
|
||||
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
|
||||
@@ -80,7 +71,7 @@ LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
|
||||
LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname);
|
||||
|
||||
/* add a symbol to the compiled program */
|
||||
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, void *val);
|
||||
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val);
|
||||
|
||||
/* output an executable, library or object file. DO NOT call
|
||||
tcc_relocate() before. */
|
||||
@@ -90,17 +81,18 @@ LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
|
||||
tcc_relocate() before. */
|
||||
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
|
||||
|
||||
/* copy code into memory passed in by the caller and do all relocations
|
||||
(needed before using tcc_get_symbol()).
|
||||
returns -1 on error and required size if ptr is NULL */
|
||||
/* do all relocations (needed before using tcc_get_symbol()) */
|
||||
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
|
||||
/* possible values for 'ptr':
|
||||
- TCC_RELOCATE_AUTO : Allocate and manage memory internally
|
||||
- NULL : return required memory size for the step below
|
||||
- memory address : copy code to memory passed by the caller
|
||||
returns -1 if error. */
|
||||
#define TCC_RELOCATE_AUTO (void*)1
|
||||
|
||||
/* return symbol value or NULL if not found */
|
||||
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
|
||||
|
||||
/* set CONFIG_TCCDIR at runtime */
|
||||
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
105
tcc-doc.texi
105
tcc-doc.texi
@@ -2,6 +2,10 @@
|
||||
@c %**start of header
|
||||
@setfilename tcc-doc.info
|
||||
@settitle Tiny C Compiler Reference Documentation
|
||||
@dircategory Software development
|
||||
@direntry
|
||||
* TCC: (tcc-doc). The Tiny C Compiler.
|
||||
@end direntry
|
||||
@c %**end of header
|
||||
|
||||
@include config.texi
|
||||
@@ -64,7 +68,7 @@ ports for the ARM (@code{arm-tcc}) and the TMS320C67xx targets
|
||||
(@code{c67-tcc}). More information about the ARM port is available at
|
||||
@url{http://lists.gnu.org/archive/html/tinycc-devel/2003-10/msg00044.html}.
|
||||
|
||||
For usage on Windows, see also tcc-win32.txt.
|
||||
For usage on Windows, see also @url{tcc-win32.txt}.
|
||||
|
||||
@node Invoke
|
||||
@chapter Command line invocation
|
||||
@@ -153,43 +157,41 @@ General Options:
|
||||
|
||||
@c man begin OPTIONS
|
||||
@table @option
|
||||
@item -v
|
||||
Display current TCC version, increase verbosity.
|
||||
|
||||
@item -c
|
||||
Generate an object file (@option{-o} option must also be given).
|
||||
Generate an object file.
|
||||
|
||||
@item -o outfile
|
||||
Put object file, executable, or dll into output file @file{outfile}.
|
||||
|
||||
@item -Bdir
|
||||
Set the path where the tcc internal libraries can be found (default is
|
||||
@file{PREFIX/lib/tcc}).
|
||||
|
||||
@item -bench
|
||||
Output compilation statistics.
|
||||
|
||||
@item -run source [args...]
|
||||
Compile file @var{source} and run it with the command line arguments
|
||||
@var{args}. In order to be able to give more than one argument to a
|
||||
script, several TCC options can be given @emph{after} the
|
||||
@option{-run} option, separated by spaces. Example:
|
||||
|
||||
@option{-run} option, separated by spaces:
|
||||
@example
|
||||
tcc "-run -L/usr/X11R6/lib -lX11" ex4.c
|
||||
@end example
|
||||
|
||||
In a script, it gives the following header:
|
||||
|
||||
@example
|
||||
#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11
|
||||
#include <stdlib.h>
|
||||
int main(int argc, char **argv)
|
||||
@{
|
||||
...
|
||||
@}
|
||||
@end example
|
||||
|
||||
@item -dumpversion
|
||||
Print only the compiler version and nothing else.
|
||||
|
||||
@item -v
|
||||
Display TCC version.
|
||||
|
||||
@item -vv
|
||||
Show included files. As sole argument, print search dirs (as below).
|
||||
|
||||
@item -bench
|
||||
Display compilation statistics.
|
||||
|
||||
@item -print-search-dirs
|
||||
Print the configured installation directory and a list of library
|
||||
and include directories tcc will search.
|
||||
|
||||
@end table
|
||||
|
||||
Preprocessor options:
|
||||
@@ -276,26 +278,31 @@ Link your program with dynamic library libxxx.so or static library
|
||||
libxxx.a. The library is searched in the paths specified by the
|
||||
@option{-L} option.
|
||||
|
||||
@item -Bdir
|
||||
Set the path where the tcc internal libraries (and include files) can be
|
||||
found (default is @file{PREFIX/lib/tcc}).
|
||||
|
||||
@item -shared
|
||||
Generate a shared library instead of an executable (@option{-o} option
|
||||
must also be given).
|
||||
Generate a shared library instead of an executable.
|
||||
|
||||
@item -soname name
|
||||
set name for shared library to be used at runtime
|
||||
|
||||
@item -static
|
||||
Generate a statically linked executable (default is a shared linked
|
||||
executable) (@option{-o} option must also be given).
|
||||
executable).
|
||||
|
||||
@item -rdynamic
|
||||
Export global symbols to the dynamic linker. It is useful when a library
|
||||
opened with @code{dlopen()} needs to access executable symbols.
|
||||
|
||||
@item -r
|
||||
Generate an object file combining all input files (@option{-o} option must
|
||||
also be given).
|
||||
Generate an object file combining all input files.
|
||||
|
||||
@item -Wl,-Ttext,address
|
||||
Set the start of the .text section to @var{address}.
|
||||
@item -Wl,-rpath=path
|
||||
Put custom seatch path for dynamic libraries into executable.
|
||||
|
||||
@item -Wl,--oformat,fmt
|
||||
@item -Wl,--oformat=fmt
|
||||
Use @var{fmt} as output format. The supported output formats are:
|
||||
@table @code
|
||||
@item elf32-i386
|
||||
@@ -306,6 +313,15 @@ Binary image (only for executable output)
|
||||
COFF output format (only for executable output for TMS320C67xx target)
|
||||
@end table
|
||||
|
||||
@item -Wl,-subsystem=console/gui/wince/...
|
||||
Set type for PE (Windows) executables.
|
||||
|
||||
@item -Wl,-[Ttext=# | section-alignment=# | file-alignment=# | image-base=# | stack=#]
|
||||
Modify executable layout.
|
||||
|
||||
@item -Wl,-Bsymbolic
|
||||
Set DT_SYMBOLIC tag.
|
||||
|
||||
@end table
|
||||
|
||||
Debugger options:
|
||||
@@ -322,12 +338,25 @@ Generate additional support code to check
|
||||
memory allocations and array/pointer bounds. @option{-g} is implied. Note
|
||||
that the generated code is slower and bigger in this case.
|
||||
|
||||
Note: @option{-b} is only available on i386 for the moment.
|
||||
|
||||
@item -bt N
|
||||
Display N callers in stack traces. This is useful with @option{-g} or
|
||||
@option{-b}.
|
||||
|
||||
@end table
|
||||
|
||||
Misc options:
|
||||
|
||||
@table @option
|
||||
@item -MD
|
||||
Generate makefile fragment with dependencies.
|
||||
|
||||
@item -MF depfile
|
||||
Use @file{depfile} as output for -MD.
|
||||
|
||||
@end table
|
||||
|
||||
Note: GCC options @option{-Ox}, @option{-fx} and @option{-mx} are
|
||||
ignored.
|
||||
@c man end
|
||||
@@ -915,9 +944,13 @@ be the best solution.
|
||||
#define VT_BTYPE 0x000f /* mask for basic type */
|
||||
#define VT_UNSIGNED 0x0010 /* unsigned type */
|
||||
#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
|
||||
#define VT_VLA 0x20000 /* VLA type (also has VT_PTR and VT_ARRAY) */
|
||||
#define VT_BITFIELD 0x0040 /* bitfield modifier */
|
||||
#define VT_CONSTANT 0x0800 /* const modifier */
|
||||
#define VT_VOLATILE 0x1000 /* volatile modifier */
|
||||
#define VT_SIGNED 0x2000 /* signed type */
|
||||
|
||||
#define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
|
||||
#define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */
|
||||
@end example
|
||||
|
||||
When a reference to another type is needed (for pointers, functions and
|
||||
@@ -928,7 +961,8 @@ The @code{VT_UNSIGNED} flag can be set for chars, shorts, ints and long
|
||||
longs.
|
||||
|
||||
Arrays are considered as pointers @code{VT_PTR} with the flag
|
||||
@code{VT_ARRAY} set.
|
||||
@code{VT_ARRAY} set. Variable length arrays are considered as special
|
||||
arrays and have flag @code{VT_VLA} set instead of @code{VT_ARRAY}.
|
||||
|
||||
The @code{VT_BITFIELD} flag can be set for chars, shorts, ints and long
|
||||
longs. If it is set, then the bitfield position is stored from bits
|
||||
@@ -944,6 +978,10 @@ integer:
|
||||
#define VT_EXTERN 0x00000080 /* extern definition */
|
||||
#define VT_STATIC 0x00000100 /* static variable */
|
||||
#define VT_TYPEDEF 0x00000200 /* typedef definition */
|
||||
#define VT_INLINE 0x00000400 /* inline definition */
|
||||
#define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */
|
||||
#define VT_EXPORT 0x00008000 /* win32: data exported from dll */
|
||||
#define VT_WEAK 0x00010000 /* win32: data exported from dll */
|
||||
@end example
|
||||
|
||||
@section Symbols
|
||||
@@ -955,7 +993,10 @@ contains @code{Sym} structures.
|
||||
an idenfier is also a token, so a string is never necessary to store
|
||||
it). @code{Sym.t} gives the type of the symbol. @code{Sym.r} is usually
|
||||
the register in which the corresponding variable is stored. @code{Sym.c} is
|
||||
usually a constant associated to the symbol.
|
||||
usually a constant associated to the symbol like its address for normal
|
||||
symbols, and the number of entries for symbols representing arrays.
|
||||
Variable length array types use @code{Sym.c} as a location on the stack
|
||||
which holds the runtime sizeof for the type.
|
||||
|
||||
Four main symbol stacks are defined:
|
||||
|
||||
|
||||
685
tcc.c
685
tcc.c
@@ -18,25 +18,28 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef ONE_SOURCE
|
||||
#include "libtcc.c"
|
||||
#else
|
||||
#include "tcc.h"
|
||||
#endif
|
||||
|
||||
void help(void)
|
||||
static void help(void)
|
||||
{
|
||||
printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
|
||||
"usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
|
||||
" [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
|
||||
" [-static] [infile1 infile2...] [-run infile args...]\n"
|
||||
"\n"
|
||||
"Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n"
|
||||
" tcc [options...] -run infile [arguments...]\n"
|
||||
"General options:\n"
|
||||
" -v display current version, increase verbosity\n"
|
||||
" -c compile only - generate an object file\n"
|
||||
" -o outfile set output filename\n"
|
||||
" -Bdir set tcc internal library path\n"
|
||||
" -bench output compilation statistics\n"
|
||||
" -run run compiled source\n"
|
||||
" -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
|
||||
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
|
||||
" -w disable all warnings\n"
|
||||
" -v show version\n"
|
||||
" -vv show included files (as sole argument: show search paths)\n"
|
||||
" -dumpversion\n"
|
||||
" -bench show compilation statistics\n"
|
||||
"Preprocessor options:\n"
|
||||
" -E preprocess only\n"
|
||||
" -Idir add include path 'dir'\n"
|
||||
@@ -45,11 +48,13 @@ void help(void)
|
||||
"Linker options:\n"
|
||||
" -Ldir add library path 'dir'\n"
|
||||
" -llib link with dynamic or static library 'lib'\n"
|
||||
" -pthread link with -lpthread and -D_REENTRANT (POSIX Linux)\n"
|
||||
" -r generate (relocatable) object file\n"
|
||||
" -rdynamic export all global symbols to dynamic linker\n"
|
||||
" -shared generate a shared library\n"
|
||||
" -soname set name for shared library to be used at runtime\n"
|
||||
" -static static linking\n"
|
||||
" -rdynamic export all global symbols to dynamic linker\n"
|
||||
" -r generate (relocatable) object file\n"
|
||||
" -Wl,-opt[=val] set linker option (see manual)\n"
|
||||
"Debugger options:\n"
|
||||
" -g generate runtime debug info\n"
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
@@ -58,98 +63,170 @@ void help(void)
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
" -bt N show N callers in stack traces\n"
|
||||
#endif
|
||||
"Misc options:\n"
|
||||
" -nostdinc do not use standard system include paths\n"
|
||||
" -nostdlib do not link with standard crt and libraries\n"
|
||||
" -Bdir use 'dir' as tcc internal library and include path\n"
|
||||
" -MD generate target dependencies for make\n"
|
||||
" -MF depfile put generated dependencies here\n"
|
||||
);
|
||||
}
|
||||
|
||||
static char **files;
|
||||
static int nb_files, nb_libraries;
|
||||
static int multiple_files;
|
||||
static int print_search_dirs;
|
||||
static int output_type;
|
||||
static int reloc_output;
|
||||
static const char *outfile;
|
||||
static int do_bench = 0;
|
||||
|
||||
#define TCC_OPTION_HAS_ARG 0x0001
|
||||
#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
|
||||
|
||||
typedef struct TCCOption {
|
||||
const char *name;
|
||||
uint16_t index;
|
||||
uint16_t flags;
|
||||
} TCCOption;
|
||||
|
||||
enum {
|
||||
TCC_OPTION_HELP,
|
||||
TCC_OPTION_I,
|
||||
TCC_OPTION_D,
|
||||
TCC_OPTION_U,
|
||||
TCC_OPTION_L,
|
||||
TCC_OPTION_B,
|
||||
TCC_OPTION_l,
|
||||
TCC_OPTION_bench,
|
||||
TCC_OPTION_bt,
|
||||
TCC_OPTION_b,
|
||||
TCC_OPTION_g,
|
||||
TCC_OPTION_c,
|
||||
TCC_OPTION_static,
|
||||
TCC_OPTION_shared,
|
||||
TCC_OPTION_soname,
|
||||
TCC_OPTION_o,
|
||||
TCC_OPTION_r,
|
||||
TCC_OPTION_Wl,
|
||||
TCC_OPTION_W,
|
||||
TCC_OPTION_O,
|
||||
TCC_OPTION_m,
|
||||
TCC_OPTION_f,
|
||||
TCC_OPTION_nostdinc,
|
||||
TCC_OPTION_nostdlib,
|
||||
TCC_OPTION_print_search_dirs,
|
||||
TCC_OPTION_rdynamic,
|
||||
TCC_OPTION_run,
|
||||
TCC_OPTION_v,
|
||||
TCC_OPTION_w,
|
||||
TCC_OPTION_pipe,
|
||||
TCC_OPTION_E,
|
||||
};
|
||||
|
||||
static const TCCOption tcc_options[] = {
|
||||
{ "h", TCC_OPTION_HELP, 0 },
|
||||
{ "?", TCC_OPTION_HELP, 0 },
|
||||
{ "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
|
||||
{ "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
|
||||
{ "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
|
||||
{ "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
|
||||
{ "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
|
||||
{ "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "bench", TCC_OPTION_bench, 0 },
|
||||
{ "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
{ "b", TCC_OPTION_b, 0 },
|
||||
/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
#ifdef _WIN32
|
||||
#include <process.h>
|
||||
static int execvp_win32(const char *prog, char **argv)
|
||||
{
|
||||
int ret = spawnvp(P_NOWAIT, prog, (char const*const*)argv);
|
||||
if (-1 == ret)
|
||||
return ret;
|
||||
cwait(&ret, ret, WAIT_CHILD);
|
||||
exit(ret);
|
||||
}
|
||||
#define execvp execvp_win32
|
||||
#endif
|
||||
{ "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "c", TCC_OPTION_c, 0 },
|
||||
{ "static", TCC_OPTION_static, 0 },
|
||||
{ "shared", TCC_OPTION_shared, 0 },
|
||||
{ "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
|
||||
{ "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
|
||||
{ "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "rdynamic", TCC_OPTION_rdynamic, 0 },
|
||||
{ "r", TCC_OPTION_r, 0 },
|
||||
{ "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
|
||||
{ "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "nostdinc", TCC_OPTION_nostdinc, 0 },
|
||||
{ "nostdlib", TCC_OPTION_nostdlib, 0 },
|
||||
{ "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
|
||||
{ "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "w", TCC_OPTION_w, 0 },
|
||||
{ "pipe", TCC_OPTION_pipe, 0},
|
||||
{ "E", TCC_OPTION_E, 0},
|
||||
{ NULL },
|
||||
};
|
||||
static void exec_other_tcc(TCCState *s, char **argv, const char *optarg)
|
||||
{
|
||||
char child_path[4096], *child_name; const char *target;
|
||||
switch (atoi(optarg)) {
|
||||
#ifdef TCC_TARGET_I386
|
||||
case 32: break;
|
||||
case 64: target = "x86_64";
|
||||
#else
|
||||
case 64: break;
|
||||
case 32: target = "i386";
|
||||
#endif
|
||||
pstrcpy(child_path, sizeof child_path - 40, argv[0]);
|
||||
child_name = tcc_basename(child_path);
|
||||
strcpy(child_name, target);
|
||||
#ifdef TCC_TARGET_PE
|
||||
strcat(child_name, "-win32");
|
||||
#endif
|
||||
strcat(child_name, "-tcc");
|
||||
if (strcmp(argv[0], child_path)) {
|
||||
if (s->verbose > 0)
|
||||
printf("tcc: using '%s'\n", child_name), fflush(stdout);
|
||||
execvp(argv[0] = child_path, argv);
|
||||
}
|
||||
tcc_error("'%s' not found", child_name);
|
||||
case 0: /* ignore -march etc. */
|
||||
break;
|
||||
default:
|
||||
tcc_warning("unsupported option \"-m%s\"", optarg);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define exec_other_tcc(s, argv, optarg)
|
||||
#endif
|
||||
|
||||
static void gen_makedeps(TCCState *s, const char *target, const char *filename)
|
||||
{
|
||||
FILE *depout;
|
||||
char buf[1024], *ext;
|
||||
int i;
|
||||
|
||||
if (!filename) {
|
||||
/* compute filename automatically
|
||||
* dir/file.o -> dir/file.d */
|
||||
pstrcpy(buf, sizeof(buf), target);
|
||||
ext = tcc_fileextension(buf);
|
||||
pstrcpy(ext, sizeof(buf) - (ext-buf), ".d");
|
||||
filename = buf;
|
||||
}
|
||||
|
||||
if (s->verbose)
|
||||
printf("<- %s\n", filename);
|
||||
|
||||
/* XXX return err codes instead of error() ? */
|
||||
depout = fopen(filename, "w");
|
||||
if (!depout)
|
||||
tcc_error("could not open '%s'", filename);
|
||||
|
||||
fprintf(depout, "%s : \\\n", target);
|
||||
for (i=0; i<s->nb_target_deps; ++i)
|
||||
fprintf(depout, " %s \\\n", s->target_deps[i]);
|
||||
fprintf(depout, "\n");
|
||||
fclose(depout);
|
||||
}
|
||||
|
||||
static char *default_outputfile(TCCState *s, const char *first_file)
|
||||
{
|
||||
char buf[1024];
|
||||
char *ext;
|
||||
const char *name = "a";
|
||||
|
||||
if (first_file && strcmp(first_file, "-"))
|
||||
name = tcc_basename(first_file);
|
||||
pstrcpy(buf, sizeof(buf), name);
|
||||
ext = tcc_fileextension(buf);
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (s->output_type == TCC_OUTPUT_DLL)
|
||||
strcpy(ext, ".dll");
|
||||
else
|
||||
if (s->output_type == TCC_OUTPUT_EXE)
|
||||
strcpy(ext, ".exe");
|
||||
else
|
||||
#endif
|
||||
if (( (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) ||
|
||||
(s->output_type == TCC_OUTPUT_PREPROCESS) )
|
||||
&& *ext)
|
||||
strcpy(ext, ".o");
|
||||
else
|
||||
strcpy(buf, "a.out");
|
||||
|
||||
return tcc_strdup(buf);
|
||||
}
|
||||
|
||||
static void print_paths(const char *msg, char **paths, int nb_paths)
|
||||
{
|
||||
int i;
|
||||
printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
|
||||
for(i = 0; i < nb_paths; i++)
|
||||
printf(" %s\n", paths[i]);
|
||||
}
|
||||
|
||||
static void display_info(TCCState *s, int what)
|
||||
{
|
||||
switch (what) {
|
||||
case 0:
|
||||
printf("tcc version %s ("
|
||||
#ifdef TCC_TARGET_I386
|
||||
"i386"
|
||||
# ifdef TCC_TARGET_PE
|
||||
" Win32"
|
||||
# endif
|
||||
#elif defined TCC_TARGET_X86_64
|
||||
"x86-64"
|
||||
# ifdef TCC_TARGET_PE
|
||||
" Win64"
|
||||
# endif
|
||||
#elif defined TCC_TARGET_ARM
|
||||
"ARM"
|
||||
# ifdef TCC_ARM_HARDFLOAT
|
||||
" Hard Float"
|
||||
# endif
|
||||
# ifdef TCC_TARGET_PE
|
||||
" WinCE"
|
||||
# endif
|
||||
#endif
|
||||
#ifndef TCC_TARGET_PE
|
||||
# ifdef __linux
|
||||
" Linux"
|
||||
# endif
|
||||
#endif
|
||||
")\n", TCC_VERSION);
|
||||
break;
|
||||
case 1:
|
||||
printf("install: %s/\n", s->tcc_lib_path);
|
||||
/* print_paths("programs", NULL, 0); */
|
||||
print_paths("crt", s->crt_paths, s->nb_crt_paths);
|
||||
print_paths("libraries", s->library_paths, s->nb_library_paths);
|
||||
print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths);
|
||||
printf("elfinterp:\n %s\n", CONFIG_TCC_ELFINTERP);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t getclock_us(void)
|
||||
{
|
||||
@@ -164,354 +241,74 @@ static int64_t getclock_us(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int strstart(const char *str, const char *val, const char **ptr)
|
||||
{
|
||||
const char *p, *q;
|
||||
p = str;
|
||||
q = val;
|
||||
while (*q != '\0') {
|
||||
if (*p != *q)
|
||||
return 0;
|
||||
p++;
|
||||
q++;
|
||||
}
|
||||
if (ptr)
|
||||
*ptr = p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* convert 'str' into an array of space separated strings */
|
||||
static int expand_args(char ***pargv, const char *str)
|
||||
{
|
||||
const char *s1;
|
||||
char **argv, *arg;
|
||||
int argc, len;
|
||||
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
for(;;) {
|
||||
while (is_space(*str))
|
||||
str++;
|
||||
if (*str == '\0')
|
||||
break;
|
||||
s1 = str;
|
||||
while (*str != '\0' && !is_space(*str))
|
||||
str++;
|
||||
len = str - s1;
|
||||
arg = tcc_malloc(len + 1);
|
||||
memcpy(arg, s1, len);
|
||||
arg[len] = '\0';
|
||||
dynarray_add((void ***)&argv, &argc, arg);
|
||||
}
|
||||
*pargv = argv;
|
||||
return argc;
|
||||
}
|
||||
|
||||
int parse_args(TCCState *s, int argc, char **argv)
|
||||
{
|
||||
int optind;
|
||||
const TCCOption *popt;
|
||||
const char *optarg, *p1, *r1;
|
||||
char *r;
|
||||
|
||||
optind = 0;
|
||||
while (optind < argc) {
|
||||
|
||||
r = argv[optind++];
|
||||
if (r[0] != '-' || r[1] == '\0') {
|
||||
/* add a new file */
|
||||
dynarray_add((void ***)&files, &nb_files, r);
|
||||
if (!multiple_files) {
|
||||
optind--;
|
||||
/* argv[0] will be this file */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* find option in table (match only the first chars */
|
||||
popt = tcc_options;
|
||||
for(;;) {
|
||||
p1 = popt->name;
|
||||
if (p1 == NULL)
|
||||
error("invalid option -- '%s'", r);
|
||||
r1 = r + 1;
|
||||
for(;;) {
|
||||
if (*p1 == '\0')
|
||||
goto option_found;
|
||||
if (*r1 != *p1)
|
||||
break;
|
||||
p1++;
|
||||
r1++;
|
||||
}
|
||||
popt++;
|
||||
}
|
||||
option_found:
|
||||
if (popt->flags & TCC_OPTION_HAS_ARG) {
|
||||
if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
|
||||
optarg = r1;
|
||||
} else {
|
||||
if (optind >= argc)
|
||||
error("argument to '%s' is missing", r);
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
} else {
|
||||
if (*r1 != '\0')
|
||||
return 0;
|
||||
optarg = NULL;
|
||||
}
|
||||
|
||||
switch(popt->index) {
|
||||
case TCC_OPTION_HELP:
|
||||
return 0;
|
||||
|
||||
case TCC_OPTION_I:
|
||||
if (tcc_add_include_path(s, optarg) < 0)
|
||||
error("too many include paths");
|
||||
break;
|
||||
case TCC_OPTION_D:
|
||||
{
|
||||
char *sym, *value;
|
||||
sym = (char *)optarg;
|
||||
value = strchr(sym, '=');
|
||||
if (value) {
|
||||
*value = '\0';
|
||||
value++;
|
||||
}
|
||||
tcc_define_symbol(s, sym, value);
|
||||
}
|
||||
break;
|
||||
case TCC_OPTION_U:
|
||||
tcc_undefine_symbol(s, optarg);
|
||||
break;
|
||||
case TCC_OPTION_L:
|
||||
tcc_add_library_path(s, optarg);
|
||||
break;
|
||||
case TCC_OPTION_B:
|
||||
/* set tcc utilities path (mainly for tcc development) */
|
||||
tcc_set_lib_path(s, optarg);
|
||||
break;
|
||||
case TCC_OPTION_l:
|
||||
dynarray_add((void ***)&files, &nb_files, r);
|
||||
nb_libraries++;
|
||||
break;
|
||||
case TCC_OPTION_bench:
|
||||
do_bench = 1;
|
||||
break;
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
case TCC_OPTION_bt:
|
||||
num_callers = atoi(optarg);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
case TCC_OPTION_b:
|
||||
s->do_bounds_check = 1;
|
||||
s->do_debug = 1;
|
||||
break;
|
||||
#endif
|
||||
case TCC_OPTION_g:
|
||||
s->do_debug = 1;
|
||||
break;
|
||||
case TCC_OPTION_c:
|
||||
multiple_files = 1;
|
||||
output_type = TCC_OUTPUT_OBJ;
|
||||
break;
|
||||
case TCC_OPTION_static:
|
||||
s->static_link = 1;
|
||||
break;
|
||||
case TCC_OPTION_shared:
|
||||
output_type = TCC_OUTPUT_DLL;
|
||||
break;
|
||||
case TCC_OPTION_soname:
|
||||
s->soname = optarg;
|
||||
break;
|
||||
case TCC_OPTION_o:
|
||||
multiple_files = 1;
|
||||
outfile = optarg;
|
||||
break;
|
||||
case TCC_OPTION_r:
|
||||
/* generate a .o merging several output files */
|
||||
reloc_output = 1;
|
||||
output_type = TCC_OUTPUT_OBJ;
|
||||
break;
|
||||
case TCC_OPTION_nostdinc:
|
||||
s->nostdinc = 1;
|
||||
break;
|
||||
case TCC_OPTION_nostdlib:
|
||||
s->nostdlib = 1;
|
||||
break;
|
||||
case TCC_OPTION_print_search_dirs:
|
||||
print_search_dirs = 1;
|
||||
break;
|
||||
case TCC_OPTION_run:
|
||||
{
|
||||
int argc1;
|
||||
char **argv1;
|
||||
argc1 = expand_args(&argv1, optarg);
|
||||
if (argc1 > 0) {
|
||||
parse_args(s, argc1, argv1);
|
||||
}
|
||||
multiple_files = 0;
|
||||
output_type = TCC_OUTPUT_MEMORY;
|
||||
}
|
||||
break;
|
||||
case TCC_OPTION_v:
|
||||
do {
|
||||
if (0 == s->verbose++)
|
||||
printf("tcc version %s\n", TCC_VERSION);
|
||||
} while (*optarg++ == 'v');
|
||||
break;
|
||||
case TCC_OPTION_f:
|
||||
if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
|
||||
goto unsupported_option;
|
||||
break;
|
||||
case TCC_OPTION_W:
|
||||
if (tcc_set_warning(s, optarg, 1) < 0 &&
|
||||
s->warn_unsupported)
|
||||
goto unsupported_option;
|
||||
break;
|
||||
case TCC_OPTION_w:
|
||||
s->warn_none = 1;
|
||||
break;
|
||||
case TCC_OPTION_rdynamic:
|
||||
s->rdynamic = 1;
|
||||
break;
|
||||
case TCC_OPTION_Wl:
|
||||
{
|
||||
const char *p;
|
||||
if (strstart(optarg, "-Ttext,", &p)) {
|
||||
s->text_addr = strtoul(p, NULL, 16);
|
||||
s->has_text_addr = 1;
|
||||
} else if (strstart(optarg, "--oformat,", &p)) {
|
||||
if (strstart(p, "elf32-", NULL)) {
|
||||
s->output_format = TCC_OUTPUT_FORMAT_ELF;
|
||||
} else if (!strcmp(p, "binary")) {
|
||||
s->output_format = TCC_OUTPUT_FORMAT_BINARY;
|
||||
} else
|
||||
#ifdef TCC_TARGET_COFF
|
||||
if (!strcmp(p, "coff")) {
|
||||
s->output_format = TCC_OUTPUT_FORMAT_COFF;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
error("target %s not found", p);
|
||||
}
|
||||
} else {
|
||||
error("unsupported linker option '%s'", optarg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TCC_OPTION_E:
|
||||
output_type = TCC_OUTPUT_PREPROCESS;
|
||||
break;
|
||||
default:
|
||||
if (s->warn_unsupported) {
|
||||
unsupported_option:
|
||||
warning("unsupported option '%s'", r);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return optind + 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
TCCState *s;
|
||||
int nb_objfiles, ret, optind;
|
||||
char objfilename[1024];
|
||||
int ret, optind, i, bench;
|
||||
int64_t start_time = 0;
|
||||
const char *first_file = NULL;
|
||||
|
||||
s = tcc_new();
|
||||
#ifdef _WIN32
|
||||
tcc_set_lib_path_w32(s);
|
||||
#endif
|
||||
output_type = TCC_OUTPUT_EXE;
|
||||
outfile = NULL;
|
||||
multiple_files = 1;
|
||||
files = NULL;
|
||||
nb_files = 0;
|
||||
nb_libraries = 0;
|
||||
reloc_output = 0;
|
||||
print_search_dirs = 0;
|
||||
ret = 0;
|
||||
s->output_type = TCC_OUTPUT_EXE;
|
||||
|
||||
optind = parse_args(s, argc - 1, argv + 1);
|
||||
if (print_search_dirs) {
|
||||
/* enough for Linux kernel */
|
||||
printf("install: %s/\n", s->tcc_lib_path);
|
||||
return 0;
|
||||
}
|
||||
if (optind == 0 || nb_files == 0) {
|
||||
if (optind && s->verbose)
|
||||
return 0;
|
||||
optind = tcc_parse_args(s, argc - 1, argv + 1);
|
||||
|
||||
if (optind == 0) {
|
||||
help();
|
||||
return 1;
|
||||
}
|
||||
|
||||
nb_objfiles = nb_files - nb_libraries;
|
||||
if (s->option_m)
|
||||
exec_other_tcc(s, argv, s->option_m);
|
||||
|
||||
/* if outfile provided without other options, we output an
|
||||
executable */
|
||||
if (outfile && output_type == TCC_OUTPUT_MEMORY)
|
||||
output_type = TCC_OUTPUT_EXE;
|
||||
if (s->verbose)
|
||||
display_info(s, 0);
|
||||
|
||||
if (s->print_search_dirs || (s->verbose == 2 && optind == 1)) {
|
||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||
display_info(s, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->verbose && optind == 1)
|
||||
return 0;
|
||||
|
||||
if (s->nb_files == 0)
|
||||
tcc_error("no input files\n");
|
||||
|
||||
/* check -c consistency : only single file handled. XXX: checks file type */
|
||||
if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
|
||||
if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
|
||||
if (s->nb_libraries != 0)
|
||||
tcc_error("cannot specify libraries with -c");
|
||||
/* accepts only a single input file */
|
||||
if (nb_objfiles != 1)
|
||||
error("cannot specify multiple files with -c");
|
||||
if (nb_libraries != 0)
|
||||
error("cannot specify libraries with -c");
|
||||
if (s->nb_files != 1)
|
||||
tcc_error("cannot specify multiple files with -c");
|
||||
}
|
||||
|
||||
|
||||
if (output_type == TCC_OUTPUT_PREPROCESS) {
|
||||
if (!outfile) {
|
||||
s->outfile = stdout;
|
||||
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||
if (!s->outfile) {
|
||||
s->ppfp = stdout;
|
||||
} else {
|
||||
s->outfile = fopen(outfile, "w");
|
||||
if (!s->outfile)
|
||||
error("could not open '%s", outfile);
|
||||
}
|
||||
} else if (output_type != TCC_OUTPUT_MEMORY) {
|
||||
if (!outfile) {
|
||||
/* compute default outfile name */
|
||||
char *ext;
|
||||
const char *name =
|
||||
strcmp(files[0], "-") == 0 ? "a" : tcc_basename(files[0]);
|
||||
pstrcpy(objfilename, sizeof(objfilename), name);
|
||||
ext = tcc_fileextension(objfilename);
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (output_type == TCC_OUTPUT_DLL)
|
||||
strcpy(ext, ".dll");
|
||||
else
|
||||
if (output_type == TCC_OUTPUT_EXE)
|
||||
strcpy(ext, ".exe");
|
||||
else
|
||||
#endif
|
||||
if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
|
||||
strcpy(ext, ".o");
|
||||
else
|
||||
pstrcpy(objfilename, sizeof(objfilename), "a.out");
|
||||
outfile = objfilename;
|
||||
s->ppfp = fopen(s->outfile, "w");
|
||||
if (!s->ppfp)
|
||||
tcc_error("could not write '%s'", s->outfile);
|
||||
}
|
||||
}
|
||||
|
||||
if (do_bench) {
|
||||
bench = s->do_bench;
|
||||
if (bench)
|
||||
start_time = getclock_us();
|
||||
}
|
||||
|
||||
tcc_set_output_type(s, output_type);
|
||||
tcc_set_output_type(s, s->output_type);
|
||||
|
||||
/* compile or add each files or library */
|
||||
for(i = 0; i < nb_files && ret == 0; i++) {
|
||||
for(i = ret = 0; i < s->nb_files && ret == 0; i++) {
|
||||
const char *filename;
|
||||
|
||||
filename = files[i];
|
||||
if (filename[0] == '-' && filename[1]) {
|
||||
filename = s->files[i];
|
||||
if (filename[0] == '-' && filename[1] == 'l') {
|
||||
if (tcc_add_library(s, filename + 2) < 0) {
|
||||
error_noabort("cannot find %s", filename);
|
||||
tcc_error_noabort("cannot find '%s'", filename);
|
||||
ret = 1;
|
||||
}
|
||||
} else {
|
||||
@@ -519,35 +316,37 @@ int main(int argc, char **argv)
|
||||
printf("-> %s\n", filename);
|
||||
if (tcc_add_file(s, filename) < 0)
|
||||
ret = 1;
|
||||
if (!first_file)
|
||||
first_file = filename;
|
||||
}
|
||||
}
|
||||
|
||||
/* free all files */
|
||||
tcc_free(files);
|
||||
if (0 == ret) {
|
||||
if (bench)
|
||||
tcc_print_stats(s, getclock_us() - start_time);
|
||||
|
||||
if (ret)
|
||||
goto the_end;
|
||||
|
||||
if (do_bench)
|
||||
tcc_print_stats(s, getclock_us() - start_time);
|
||||
|
||||
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||
if (outfile)
|
||||
fclose(s->outfile);
|
||||
} else if (s->output_type == TCC_OUTPUT_MEMORY) {
|
||||
ret = tcc_run(s, argc - optind, argv + optind);
|
||||
} else
|
||||
ret = tcc_output_file(s, outfile) ? 1 : 0;
|
||||
the_end:
|
||||
/* XXX: cannot do it with bound checking because of the malloc hooks */
|
||||
if (!s->do_bounds_check)
|
||||
tcc_delete(s);
|
||||
|
||||
#ifdef MEM_DEBUG
|
||||
if (do_bench) {
|
||||
printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
|
||||
}
|
||||
if (s->output_type == TCC_OUTPUT_MEMORY) {
|
||||
#ifdef TCC_IS_NATIVE
|
||||
ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind);
|
||||
#else
|
||||
tcc_error_noabort("-run is not available in a cross compiler");
|
||||
ret = 1;
|
||||
#endif
|
||||
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||
if (s->outfile)
|
||||
fclose(s->ppfp);
|
||||
} else {
|
||||
if (!s->outfile)
|
||||
s->outfile = default_outputfile(s, first_file);
|
||||
ret = !!tcc_output_file(s, s->outfile);
|
||||
/* dump collected dependencies */
|
||||
if (s->gen_deps && !ret)
|
||||
gen_makedeps(s, s->outfile, s->deps_outfile);
|
||||
}
|
||||
}
|
||||
|
||||
tcc_delete(s);
|
||||
if (bench)
|
||||
tcc_memstats();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
229
tccasm.c
229
tccasm.c
@@ -18,7 +18,10 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
static int asm_get_local_label_name(TCCState *s1, unsigned int n)
|
||||
#include "tcc.h"
|
||||
#ifdef CONFIG_TCC_ASM
|
||||
|
||||
ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)
|
||||
{
|
||||
char buf[64];
|
||||
TokenSym *ts;
|
||||
@@ -28,7 +31,7 @@ static int asm_get_local_label_name(TCCState *s1, unsigned int n)
|
||||
return ts->tok;
|
||||
}
|
||||
|
||||
static void asm_expr(TCCState *s1, ExprValue *pe);
|
||||
ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
|
||||
|
||||
/* We do not use the C expression parser to handle symbols. Maybe the
|
||||
C expression parser could be tweaked to do so. */
|
||||
@@ -52,7 +55,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
||||
if (sym && sym->r == 0)
|
||||
sym = sym->prev_tok;
|
||||
if (!sym)
|
||||
error("local label '%d' not found backward", n);
|
||||
tcc_error("local label '%d' not found backward", n);
|
||||
} else {
|
||||
/* forward */
|
||||
if (!sym || sym->r) {
|
||||
@@ -67,7 +70,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
||||
pe->v = n;
|
||||
pe->sym = NULL;
|
||||
} else {
|
||||
error("invalid number syntax");
|
||||
tcc_error("invalid number syntax");
|
||||
}
|
||||
next();
|
||||
break;
|
||||
@@ -81,7 +84,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
||||
next();
|
||||
asm_expr_unary(s1, pe);
|
||||
if (pe->sym)
|
||||
error("invalid operation with label");
|
||||
tcc_error("invalid operation with label");
|
||||
if (op == '-')
|
||||
pe->v = -pe->v;
|
||||
else
|
||||
@@ -109,7 +112,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
||||
}
|
||||
if (sym->r == SHN_ABS) {
|
||||
/* if absolute symbol, no need to put a symbol value */
|
||||
pe->v = (long)sym->next;
|
||||
pe->v = sym->jnext;
|
||||
pe->sym = NULL;
|
||||
} else {
|
||||
pe->v = 0;
|
||||
@@ -117,7 +120,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
||||
}
|
||||
next();
|
||||
} else {
|
||||
error("bad expression syntax [%s]", get_tok_str(tok, &tokc));
|
||||
tcc_error("bad expression syntax [%s]", get_tok_str(tok, &tokc));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -137,7 +140,7 @@ static void asm_expr_prod(TCCState *s1, ExprValue *pe)
|
||||
next();
|
||||
asm_expr_unary(s1, &e2);
|
||||
if (pe->sym || e2.sym)
|
||||
error("invalid operation with label");
|
||||
tcc_error("invalid operation with label");
|
||||
switch(op) {
|
||||
case '*':
|
||||
pe->v *= e2.v;
|
||||
@@ -145,7 +148,7 @@ static void asm_expr_prod(TCCState *s1, ExprValue *pe)
|
||||
case '/':
|
||||
if (e2.v == 0) {
|
||||
div_error:
|
||||
error("division by zero");
|
||||
tcc_error("division by zero");
|
||||
}
|
||||
pe->v /= e2.v;
|
||||
break;
|
||||
@@ -178,7 +181,7 @@ static void asm_expr_logic(TCCState *s1, ExprValue *pe)
|
||||
next();
|
||||
asm_expr_prod(s1, &e2);
|
||||
if (pe->sym || e2.sym)
|
||||
error("invalid operation with label");
|
||||
tcc_error("invalid operation with label");
|
||||
switch(op) {
|
||||
case '&':
|
||||
pe->v &= e2.v;
|
||||
@@ -225,25 +228,25 @@ static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
|
||||
/* OK */
|
||||
} else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) {
|
||||
/* we also accept defined symbols in the same section */
|
||||
pe->v += (long)pe->sym->next - (long)e2.sym->next;
|
||||
pe->v += pe->sym->jnext - e2.sym->jnext;
|
||||
} else {
|
||||
goto cannot_relocate;
|
||||
}
|
||||
pe->sym = NULL; /* same symbols can be substracted to NULL */
|
||||
} else {
|
||||
cannot_relocate:
|
||||
error("invalid operation with label");
|
||||
tcc_error("invalid operation with label");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void asm_expr(TCCState *s1, ExprValue *pe)
|
||||
ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe)
|
||||
{
|
||||
asm_expr_sum(s1, pe);
|
||||
}
|
||||
|
||||
static int asm_int_expr(TCCState *s1)
|
||||
ST_FUNC int asm_int_expr(TCCState *s1)
|
||||
{
|
||||
ExprValue e;
|
||||
asm_expr(s1, &e);
|
||||
@@ -264,7 +267,7 @@ static void asm_new_label1(TCCState *s1, int label, int is_local,
|
||||
if (sym->r) {
|
||||
/* the label is already defined */
|
||||
if (!is_local) {
|
||||
error("assembler label '%s' already defined",
|
||||
tcc_error("assembler label '%s' already defined",
|
||||
get_tok_str(label, NULL));
|
||||
} else {
|
||||
/* redefinition of local labels is possible */
|
||||
@@ -277,7 +280,7 @@ static void asm_new_label1(TCCState *s1, int label, int is_local,
|
||||
sym->type.t = VT_STATIC | VT_VOID;
|
||||
}
|
||||
sym->r = sh_num;
|
||||
sym->next = (void *)value;
|
||||
sym->jnext = value;
|
||||
}
|
||||
|
||||
static void asm_new_label(TCCState *s1, int label, int is_local)
|
||||
@@ -298,7 +301,7 @@ static void asm_free_labels(TCCState *st)
|
||||
sec = SECTION_ABS;
|
||||
else
|
||||
sec = st->sections[s->r];
|
||||
put_extern_sym2(s, sec, (long)s->next, 0, 0);
|
||||
put_extern_sym2(s, sec, s->jnext, 0, 0);
|
||||
}
|
||||
/* remove label */
|
||||
table_ident[s->v - TOK_IDENT]->sym_label = NULL;
|
||||
@@ -339,7 +342,7 @@ static void asm_parse_directive(TCCState *s1)
|
||||
n = asm_int_expr(s1);
|
||||
if (tok1 == TOK_ASM_align) {
|
||||
if (n < 0 || (n & (n-1)) != 0)
|
||||
error("alignment must be a positive power of two");
|
||||
tcc_error("alignment must be a positive power of two");
|
||||
offset = (ind + n - 1) & -n;
|
||||
size = offset - ind;
|
||||
/* the section must have a compatible alignment */
|
||||
@@ -370,7 +373,7 @@ static void asm_parse_directive(TCCState *s1)
|
||||
p = tokc.cstr->data;
|
||||
if (tok != TOK_PPNUM) {
|
||||
error_constant:
|
||||
error("64 bit constant");
|
||||
tcc_error("64 bit constant");
|
||||
}
|
||||
vl = strtoll(p, (char **)&p, 0);
|
||||
if (*p != '\0')
|
||||
@@ -429,7 +432,7 @@ static void asm_parse_directive(TCCState *s1)
|
||||
next();
|
||||
repeat = asm_int_expr(s1);
|
||||
if (repeat < 0) {
|
||||
error("repeat < 0; .fill ignored");
|
||||
tcc_error("repeat < 0; .fill ignored");
|
||||
break;
|
||||
}
|
||||
size = 1;
|
||||
@@ -438,7 +441,7 @@ static void asm_parse_directive(TCCState *s1)
|
||||
next();
|
||||
size = asm_int_expr(s1);
|
||||
if (size < 0) {
|
||||
error("size < 0; .fill ignored");
|
||||
tcc_error("size < 0; .fill ignored");
|
||||
break;
|
||||
}
|
||||
if (size > 8)
|
||||
@@ -471,7 +474,7 @@ static void asm_parse_directive(TCCState *s1)
|
||||
/* XXX: handle section symbols too */
|
||||
n = asm_int_expr(s1);
|
||||
if (n < ind)
|
||||
error("attempt to .org backwards");
|
||||
tcc_error("attempt to .org backwards");
|
||||
v = 0;
|
||||
size = n - ind;
|
||||
goto zero_pad;
|
||||
@@ -479,7 +482,9 @@ static void asm_parse_directive(TCCState *s1)
|
||||
break;
|
||||
case TOK_ASM_globl:
|
||||
case TOK_ASM_global:
|
||||
{
|
||||
case TOK_ASM_weak:
|
||||
tok1 = tok;
|
||||
do {
|
||||
Sym *sym;
|
||||
|
||||
next();
|
||||
@@ -489,8 +494,10 @@ static void asm_parse_directive(TCCState *s1)
|
||||
sym->type.t = VT_VOID;
|
||||
}
|
||||
sym->type.t &= ~VT_STATIC;
|
||||
if (tok1 == TOK_ASM_weak)
|
||||
sym->type.t |= VT_WEAK;
|
||||
next();
|
||||
}
|
||||
} while (tok == ',');
|
||||
break;
|
||||
case TOK_ASM_string:
|
||||
case TOK_ASM_ascii:
|
||||
@@ -535,6 +542,95 @@ static void asm_parse_directive(TCCState *s1)
|
||||
use_section(s1, sname);
|
||||
}
|
||||
break;
|
||||
case TOK_ASM_file:
|
||||
{
|
||||
char filename[512];
|
||||
|
||||
filename[0] = '\0';
|
||||
next();
|
||||
|
||||
if (tok == TOK_STR)
|
||||
pstrcat(filename, sizeof(filename), tokc.cstr->data);
|
||||
else
|
||||
pstrcat(filename, sizeof(filename), get_tok_str(tok, NULL));
|
||||
|
||||
if (s1->warn_unsupported)
|
||||
tcc_warning("ignoring .file %s", filename);
|
||||
|
||||
next();
|
||||
}
|
||||
break;
|
||||
case TOK_ASM_ident:
|
||||
{
|
||||
char ident[256];
|
||||
|
||||
ident[0] = '\0';
|
||||
next();
|
||||
|
||||
if (tok == TOK_STR)
|
||||
pstrcat(ident, sizeof(ident), tokc.cstr->data);
|
||||
else
|
||||
pstrcat(ident, sizeof(ident), get_tok_str(tok, NULL));
|
||||
|
||||
if (s1->warn_unsupported)
|
||||
tcc_warning("ignoring .ident %s", ident);
|
||||
|
||||
next();
|
||||
}
|
||||
break;
|
||||
case TOK_ASM_size:
|
||||
{
|
||||
Sym *sym;
|
||||
|
||||
next();
|
||||
sym = label_find(tok);
|
||||
if (!sym) {
|
||||
tcc_error("label not found: %s", get_tok_str(tok, NULL));
|
||||
}
|
||||
|
||||
next();
|
||||
skip(',');
|
||||
/* XXX .size name,label2-label1 */
|
||||
if (s1->warn_unsupported)
|
||||
tcc_warning("ignoring .size %s,*", get_tok_str(tok, NULL));
|
||||
|
||||
while (tok != '\n' && tok != CH_EOF) {
|
||||
next();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TOK_ASM_type:
|
||||
{
|
||||
Sym *sym;
|
||||
const char *newtype;
|
||||
|
||||
next();
|
||||
sym = label_find(tok);
|
||||
if (!sym) {
|
||||
sym = label_push(&s1->asm_labels, tok, 0);
|
||||
sym->type.t = VT_VOID;
|
||||
}
|
||||
|
||||
next();
|
||||
skip(',');
|
||||
if (tok == TOK_STR) {
|
||||
newtype = tokc.cstr->data;
|
||||
} else {
|
||||
if (tok == '@' || tok == '%')
|
||||
skip(tok);
|
||||
newtype = get_tok_str(tok, NULL);
|
||||
}
|
||||
|
||||
if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) {
|
||||
sym->type.t = VT_FUNC;
|
||||
}
|
||||
else if (s1->warn_unsupported)
|
||||
tcc_warning("change type of '%s' from 0x%x to '%s' ignored",
|
||||
get_tok_str(sym->v, NULL), sym->type.t, newtype);
|
||||
|
||||
next();
|
||||
}
|
||||
break;
|
||||
case TOK_SECTION1:
|
||||
{
|
||||
char sname[256];
|
||||
@@ -565,14 +661,34 @@ static void asm_parse_directive(TCCState *s1)
|
||||
Section *sec;
|
||||
next();
|
||||
if (!last_text_section)
|
||||
error("no previous section referenced");
|
||||
tcc_error("no previous section referenced");
|
||||
sec = cur_text_section;
|
||||
use_section1(s1, last_text_section);
|
||||
last_text_section = sec;
|
||||
}
|
||||
break;
|
||||
#ifdef TCC_TARGET_I386
|
||||
case TOK_ASM_code16:
|
||||
{
|
||||
next();
|
||||
s1->seg_size = 16;
|
||||
}
|
||||
break;
|
||||
case TOK_ASM_code32:
|
||||
{
|
||||
next();
|
||||
s1->seg_size = 32;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
/* added for compatibility with GAS */
|
||||
case TOK_ASM_code64:
|
||||
next();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
|
||||
tcc_error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -679,7 +795,7 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
|
||||
}
|
||||
|
||||
/* Assemble the current file */
|
||||
static int tcc_assemble(TCCState *s1, int do_preprocess)
|
||||
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
|
||||
{
|
||||
Sym *define_start;
|
||||
int ret;
|
||||
@@ -692,6 +808,12 @@ static int tcc_assemble(TCCState *s1, int do_preprocess)
|
||||
|
||||
define_start = define_stack;
|
||||
|
||||
/* an elf symbol of type STT_FILE must be put so that STB_LOCAL
|
||||
symbols can be safely used */
|
||||
put_elf_sym(symtab_section, 0, 0,
|
||||
ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
|
||||
SHN_ABS, file->filename);
|
||||
|
||||
ret = tcc_assemble_internal(s1, do_preprocess);
|
||||
|
||||
cur_text_section->data_offset = ind;
|
||||
@@ -709,37 +831,27 @@ static int tcc_assemble(TCCState *s1, int do_preprocess)
|
||||
end */
|
||||
static void tcc_assemble_inline(TCCState *s1, char *str, int len)
|
||||
{
|
||||
BufferedFile *bf, *saved_file;
|
||||
int saved_parse_flags, *saved_macro_ptr;
|
||||
int saved_parse_flags;
|
||||
const int *saved_macro_ptr;
|
||||
|
||||
bf = tcc_malloc(sizeof(BufferedFile));
|
||||
memset(bf, 0, sizeof(BufferedFile));
|
||||
bf->fd = -1;
|
||||
bf->buf_ptr = str;
|
||||
bf->buf_end = str + len;
|
||||
str[len] = CH_EOB;
|
||||
/* same name as current file so that errors are correctly
|
||||
reported */
|
||||
pstrcpy(bf->filename, sizeof(bf->filename), file->filename);
|
||||
bf->line_num = file->line_num;
|
||||
saved_file = file;
|
||||
file = bf;
|
||||
saved_parse_flags = parse_flags;
|
||||
saved_macro_ptr = macro_ptr;
|
||||
|
||||
tcc_open_bf(s1, ":asm:", len);
|
||||
memcpy(file->buffer, str, len);
|
||||
|
||||
macro_ptr = NULL;
|
||||
|
||||
tcc_assemble_internal(s1, 0);
|
||||
tcc_close();
|
||||
|
||||
parse_flags = saved_parse_flags;
|
||||
macro_ptr = saved_macro_ptr;
|
||||
file = saved_file;
|
||||
tcc_free(bf);
|
||||
}
|
||||
|
||||
/* find a constraint by its number or id (gcc 3 extended
|
||||
syntax). return -1 if not found. Return in *pp in char after the
|
||||
constraint */
|
||||
static int find_constraint(ASMOperand *operands, int nb_operands,
|
||||
ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands,
|
||||
const char *name, const char **pp)
|
||||
{
|
||||
int index;
|
||||
@@ -801,7 +913,7 @@ static void subst_asm_operands(ASMOperand *operands, int nb_operands,
|
||||
modifier = *str++;
|
||||
index = find_constraint(operands, nb_operands, str, &str);
|
||||
if (index < 0)
|
||||
error("invalid operand reference after %%");
|
||||
tcc_error("invalid operand reference after %%");
|
||||
op = &operands[index];
|
||||
sv = *op->vt;
|
||||
if (op->reg >= 0) {
|
||||
@@ -830,7 +942,7 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
||||
nb_operands = *nb_operands_ptr;
|
||||
for(;;) {
|
||||
if (nb_operands >= MAX_ASM_OPERANDS)
|
||||
error("too many asm operands");
|
||||
tcc_error("too many asm operands");
|
||||
op = &operands[nb_operands++];
|
||||
op->id = 0;
|
||||
if (tok == '[') {
|
||||
@@ -874,27 +986,12 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_asm_str(CString *astr)
|
||||
{
|
||||
skip('(');
|
||||
/* read the string */
|
||||
if (tok != TOK_STR)
|
||||
expect("string constant");
|
||||
cstr_new(astr);
|
||||
while (tok == TOK_STR) {
|
||||
/* XXX: add \0 handling too ? */
|
||||
cstr_cat(astr, tokc.cstr->data);
|
||||
next();
|
||||
}
|
||||
cstr_ccat(astr, '\0');
|
||||
}
|
||||
|
||||
/* parse the GCC asm() instruction */
|
||||
static void asm_instr(void)
|
||||
ST_FUNC void asm_instr(void)
|
||||
{
|
||||
CString astr, astr1;
|
||||
ASMOperand operands[MAX_ASM_OPERANDS];
|
||||
int nb_inputs, nb_outputs, nb_operands, i, must_subst, out_reg;
|
||||
int nb_outputs, nb_operands, i, must_subst, out_reg;
|
||||
uint8_t clobber_regs[NB_ASM_REGS];
|
||||
|
||||
next();
|
||||
@@ -943,7 +1040,6 @@ static void asm_instr(void)
|
||||
token after the assembler parsing */
|
||||
if (tok != ';')
|
||||
expect("';'");
|
||||
nb_inputs = nb_operands - nb_outputs;
|
||||
|
||||
/* save all values in the memory */
|
||||
save_regs(0);
|
||||
@@ -991,7 +1087,7 @@ static void asm_instr(void)
|
||||
cstr_free(&astr1);
|
||||
}
|
||||
|
||||
static void asm_global_instr(void)
|
||||
ST_FUNC void asm_global_instr(void)
|
||||
{
|
||||
CString astr;
|
||||
|
||||
@@ -1019,3 +1115,4 @@ static void asm_global_instr(void)
|
||||
|
||||
cstr_free(&astr);
|
||||
}
|
||||
#endif /* CONFIG_TCC_ASM */
|
||||
|
||||
55
tcccoff.c
55
tcccoff.c
@@ -18,7 +18,8 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "coff.h"
|
||||
|
||||
#include "tcc.h"
|
||||
|
||||
#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
|
||||
#define MAX_STR_TABLE 1000000
|
||||
@@ -37,7 +38,7 @@ int EndAddress[MAX_FUNCS];
|
||||
int LastLineNo[MAX_FUNCS];
|
||||
int FuncEntries[MAX_FUNCS];
|
||||
|
||||
BOOL OutputTheSection(Section * sect);
|
||||
int OutputTheSection(Section * sect);
|
||||
short int GetCoffFlags(const char *s);
|
||||
void SortSymbolTable(void);
|
||||
Section *FindSection(TCCState * s1, const char *sname);
|
||||
@@ -73,7 +74,7 @@ typedef struct {
|
||||
unsigned short dummy4;
|
||||
} AUXEF;
|
||||
|
||||
int tcc_output_coff(TCCState *s1, FILE *f)
|
||||
ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
||||
{
|
||||
Section *tcc_sect;
|
||||
SCNHDR *coff_sec;
|
||||
@@ -532,7 +533,7 @@ int tcc_output_coff(TCCState *s1, FILE *f)
|
||||
} else {
|
||||
if (pCoff_str_table - Coff_str_table + strlen(name) >
|
||||
MAX_STR_TABLE - 1)
|
||||
error("String table too large");
|
||||
tcc_error("String table too large");
|
||||
|
||||
csym._n._n_n._n_zeroes = 0;
|
||||
csym._n._n_n._n_offset =
|
||||
@@ -562,11 +563,7 @@ int tcc_output_coff(TCCState *s1, FILE *f)
|
||||
}
|
||||
|
||||
if (k >= nFuncs) {
|
||||
char s[256];
|
||||
|
||||
sprintf(s, "debug info can't find function: %s", name);
|
||||
|
||||
error(s);
|
||||
tcc_error("debug info can't find function: %s", name);
|
||||
}
|
||||
// put a Function Name
|
||||
|
||||
@@ -733,13 +730,7 @@ void SortSymbolTable(void)
|
||||
}
|
||||
|
||||
if (k >= nFuncs) {
|
||||
char s[256];
|
||||
|
||||
sprintf(s,
|
||||
"debug (sort) info can't find function: %s",
|
||||
name2);
|
||||
|
||||
error(s);
|
||||
tcc_error("debug (sort) info can't find function: %s", name2);
|
||||
}
|
||||
|
||||
if (strcmp(AssociatedFile[k], name) == 0) {
|
||||
@@ -766,7 +757,7 @@ void SortSymbolTable(void)
|
||||
}
|
||||
|
||||
if (n != nb_syms)
|
||||
error("Internal Compiler error, debug info");
|
||||
tcc_error("Internal Compiler error, debug info");
|
||||
|
||||
// copy it all back
|
||||
|
||||
@@ -823,14 +814,14 @@ int FindCoffSymbolIndex(const char *func_name)
|
||||
return n; // total number of symbols
|
||||
}
|
||||
|
||||
BOOL OutputTheSection(Section * sect)
|
||||
int OutputTheSection(Section * sect)
|
||||
{
|
||||
const char *s = sect->name;
|
||||
|
||||
if (!strcmp(s, ".text"))
|
||||
return true;
|
||||
return 1;
|
||||
else if (!strcmp(s, ".data"))
|
||||
return true;
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
@@ -863,11 +854,11 @@ Section *FindSection(TCCState * s1, const char *sname)
|
||||
return s;
|
||||
}
|
||||
|
||||
error("could not find section %s", sname);
|
||||
tcc_error("could not find section %s", sname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tcc_load_coff(TCCState * s1, int fd)
|
||||
ST_FUNC int tcc_load_coff(TCCState * s1, int fd)
|
||||
{
|
||||
// tktk TokenSym *ts;
|
||||
|
||||
@@ -881,39 +872,39 @@ int tcc_load_coff(TCCState * s1, int fd)
|
||||
|
||||
f = fdopen(fd, "rb");
|
||||
if (!f) {
|
||||
error("Unable to open .out file for input");
|
||||
tcc_error("Unable to open .out file for input");
|
||||
}
|
||||
|
||||
if (fread(&file_hdr, FILHSZ, 1, f) != 1)
|
||||
error("error reading .out file for input");
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1)
|
||||
error("error reading .out file for input");
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
// first read the string table
|
||||
|
||||
if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET))
|
||||
error("error reading .out file for input");
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
if (fread(&str_size, sizeof(int), 1, f) != 1)
|
||||
error("error reading .out file for input");
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
|
||||
Coff_str_table = (char *) tcc_malloc(str_size);
|
||||
|
||||
if (fread(Coff_str_table, str_size - 4, 1, f) != 1)
|
||||
error("error reading .out file for input");
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
// read/process all the symbols
|
||||
|
||||
// seek back to symbols
|
||||
|
||||
if (fseek(f, file_hdr.f_symptr, SEEK_SET))
|
||||
error("error reading .out file for input");
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
for (i = 0; i < file_hdr.f_nsyms; i++) {
|
||||
if (fread(&csym, SYMESZ, 1, f) != 1)
|
||||
error("error reading .out file for input");
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
if (csym._n._n_n._n_zeroes == 0) {
|
||||
name = Coff_str_table + csym._n._n_n._n_offset - 4;
|
||||
@@ -942,13 +933,13 @@ int tcc_load_coff(TCCState * s1, int fd)
|
||||
if (name[0] == '_' && strcmp(name, "_main") != 0)
|
||||
name++;
|
||||
|
||||
tcc_add_symbol(s1, name, (void*)csym.n_value);
|
||||
tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value);
|
||||
}
|
||||
// skip any aux records
|
||||
|
||||
if (csym.n_numaux == 1) {
|
||||
if (fread(&csym, SYMESZ, 1, f) != 1)
|
||||
error("error reading .out file for input");
|
||||
tcc_error("error reading .out file for input");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
732
tccrun.c
Normal file
732
tccrun.c
Normal file
@@ -0,0 +1,732 @@
|
||||
/*
|
||||
* TCC - Tiny C Compiler - Support for -run switch
|
||||
*
|
||||
* Copyright (c) 2001-2004 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "tcc.h"
|
||||
|
||||
/* only native compiler supports -run */
|
||||
#ifdef TCC_IS_NATIVE
|
||||
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
ST_DATA int rt_num_callers = 6;
|
||||
ST_DATA const char **rt_bound_error_msg;
|
||||
ST_DATA void *rt_prog_main;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ucontext_t CONTEXT
|
||||
#endif
|
||||
|
||||
static void set_pages_executable(void *ptr, unsigned long length);
|
||||
static void set_exception_handler(void);
|
||||
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level);
|
||||
static void rt_error(ucontext_t *uc, const char *fmt, ...);
|
||||
static int tcc_relocate_ex(TCCState *s1, void *ptr);
|
||||
|
||||
#ifdef _WIN64
|
||||
static void win64_add_function_table(TCCState *s1);
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/* Do all relocations (needed before using tcc_get_symbol())
|
||||
Returns -1 on error. */
|
||||
|
||||
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (TCC_RELOCATE_AUTO != ptr)
|
||||
return tcc_relocate_ex(s1, ptr);
|
||||
|
||||
ret = tcc_relocate_ex(s1, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
{ /* Use mmap instead of malloc for Selinux. Ref:
|
||||
http://www.gnu.org/s/libc/manual/html_node/File-Size.html */
|
||||
|
||||
char tmpfname[] = "/tmp/.tccrunXXXXXX";
|
||||
int fd = mkstemp (tmpfname);
|
||||
|
||||
s1->mem_size = ret;
|
||||
unlink (tmpfname);
|
||||
ftruncate (fd, s1->mem_size);
|
||||
|
||||
s1->write_mem = mmap (NULL, ret, PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED, fd, 0);
|
||||
if (s1->write_mem == MAP_FAILED)
|
||||
tcc_error("/tmp not writeable");
|
||||
|
||||
s1->runtime_mem = mmap (NULL, ret, PROT_READ|PROT_EXEC,
|
||||
MAP_SHARED, fd, 0);
|
||||
if (s1->runtime_mem == MAP_FAILED)
|
||||
tcc_error("/tmp not executable");
|
||||
|
||||
ret = tcc_relocate_ex(s1, s1->write_mem);
|
||||
}
|
||||
#else
|
||||
s1->runtime_mem = tcc_malloc(ret);
|
||||
ret = tcc_relocate_ex(s1, s1->runtime_mem);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* launch the compiled program with the given arguments */
|
||||
LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||
{
|
||||
int (*prog_main)(int, char **);
|
||||
int ret;
|
||||
|
||||
if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
|
||||
return -1;
|
||||
|
||||
prog_main = tcc_get_symbol_err(s1, "main");
|
||||
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
if (s1->do_debug) {
|
||||
set_exception_handler();
|
||||
rt_prog_main = prog_main;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (s1->do_bounds_check) {
|
||||
void (*bound_init)(void);
|
||||
void (*bound_exit)(void);
|
||||
/* set error function */
|
||||
rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");
|
||||
/* XXX: use .init section so that it also work in binary ? */
|
||||
bound_init = tcc_get_symbol_err(s1, "__bound_init");
|
||||
bound_exit = tcc_get_symbol_err(s1, "__bound_exit");
|
||||
bound_init();
|
||||
ret = (*prog_main)(argc, argv);
|
||||
bound_exit();
|
||||
} else
|
||||
#endif
|
||||
ret = (*prog_main)(argc, argv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* relocate code. Return -1 on error, required size if ptr is NULL,
|
||||
otherwise copy code into buffer passed by the caller */
|
||||
static int tcc_relocate_ex(TCCState *s1, void *ptr)
|
||||
{
|
||||
Section *s;
|
||||
unsigned long offset, length;
|
||||
addr_t mem;
|
||||
int i;
|
||||
|
||||
if (NULL == ptr) {
|
||||
s1->nb_errors = 0;
|
||||
#ifdef TCC_TARGET_PE
|
||||
pe_output_file(s1, NULL);
|
||||
#else
|
||||
tcc_add_runtime(s1);
|
||||
relocate_common_syms();
|
||||
tcc_add_linker_symbols(s1);
|
||||
build_got_entries(s1);
|
||||
#endif
|
||||
if (s1->nb_errors)
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset = 0, mem = (addr_t)ptr;
|
||||
for(i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
if (0 == (s->sh_flags & SHF_ALLOC))
|
||||
continue;
|
||||
length = s->data_offset;
|
||||
s->sh_addr = mem ? (mem + offset + 15) & ~15 : 0;
|
||||
offset = (offset + length + 15) & ~15;
|
||||
}
|
||||
offset += 16;
|
||||
|
||||
/* relocate symbols */
|
||||
relocate_syms(s1, 1);
|
||||
if (s1->nb_errors)
|
||||
return -1;
|
||||
|
||||
#ifdef TCC_HAS_RUNTIME_PLTGOT
|
||||
s1->runtime_plt_and_got_offset = 0;
|
||||
s1->runtime_plt_and_got = (char *)(mem + offset);
|
||||
/* double the size of the buffer for got and plt entries
|
||||
XXX: calculate exact size for them? */
|
||||
offset *= 2;
|
||||
#endif
|
||||
|
||||
if (0 == mem)
|
||||
return offset;
|
||||
|
||||
/* relocate each section */
|
||||
for(i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
if (s->reloc)
|
||||
relocate_section(s1, s);
|
||||
}
|
||||
|
||||
for(i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
if (0 == (s->sh_flags & SHF_ALLOC))
|
||||
continue;
|
||||
length = s->data_offset;
|
||||
// printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
|
||||
ptr = (void*)s->sh_addr;
|
||||
if (NULL == s->data || s->sh_type == SHT_NOBITS)
|
||||
memset(ptr, 0, length);
|
||||
else
|
||||
memcpy(ptr, s->data, length);
|
||||
/* mark executable sections as executable in memory */
|
||||
if (s->sh_flags & SHF_EXECINSTR)
|
||||
set_pages_executable(ptr, length);
|
||||
}
|
||||
|
||||
#ifdef TCC_HAS_RUNTIME_PLTGOT
|
||||
set_pages_executable(s1->runtime_plt_and_got,
|
||||
s1->runtime_plt_and_got_offset);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN64
|
||||
win64_add_function_table(s1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/* allow to run code in memory */
|
||||
|
||||
static void set_pages_executable(void *ptr, unsigned long length)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
unsigned long old_protect;
|
||||
VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
|
||||
#else
|
||||
#ifndef PAGESIZE
|
||||
# define PAGESIZE 4096
|
||||
#endif
|
||||
addr_t start, end;
|
||||
start = (addr_t)ptr & ~(PAGESIZE - 1);
|
||||
end = (addr_t)ptr + length;
|
||||
end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
|
||||
mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
|
||||
ST_FUNC void tcc_set_num_callers(int n)
|
||||
{
|
||||
rt_num_callers = n;
|
||||
}
|
||||
|
||||
/* print the position in the source file of PC value 'pc' by reading
|
||||
the stabs debug information */
|
||||
static addr_t rt_printline(addr_t wanted_pc, const char *msg)
|
||||
{
|
||||
char func_name[128], last_func_name[128];
|
||||
addr_t func_addr, last_pc, pc;
|
||||
const char *incl_files[INCLUDE_STACK_SIZE];
|
||||
int incl_index, len, last_line_num, i;
|
||||
const char *str, *p;
|
||||
|
||||
Stab_Sym *stab_sym = NULL, *stab_sym_end, *sym;
|
||||
int stab_len = 0;
|
||||
char *stab_str = NULL;
|
||||
|
||||
if (stab_section) {
|
||||
stab_len = stab_section->data_offset;
|
||||
stab_sym = (Stab_Sym *)stab_section->data;
|
||||
stab_str = stabstr_section->data;
|
||||
}
|
||||
|
||||
func_name[0] = '\0';
|
||||
func_addr = 0;
|
||||
incl_index = 0;
|
||||
last_func_name[0] = '\0';
|
||||
last_pc = (addr_t)-1;
|
||||
last_line_num = 1;
|
||||
|
||||
if (!stab_sym)
|
||||
goto no_stabs;
|
||||
|
||||
stab_sym_end = (Stab_Sym*)((char*)stab_sym + stab_len);
|
||||
for (sym = stab_sym + 1; sym < stab_sym_end; ++sym) {
|
||||
switch(sym->n_type) {
|
||||
/* function start or end */
|
||||
case N_FUN:
|
||||
if (sym->n_strx == 0) {
|
||||
/* we test if between last line and end of function */
|
||||
pc = sym->n_value + func_addr;
|
||||
if (wanted_pc >= last_pc && wanted_pc < pc)
|
||||
goto found;
|
||||
func_name[0] = '\0';
|
||||
func_addr = 0;
|
||||
} else {
|
||||
str = stab_str + sym->n_strx;
|
||||
p = strchr(str, ':');
|
||||
if (!p) {
|
||||
pstrcpy(func_name, sizeof(func_name), str);
|
||||
} else {
|
||||
len = p - str;
|
||||
if (len > sizeof(func_name) - 1)
|
||||
len = sizeof(func_name) - 1;
|
||||
memcpy(func_name, str, len);
|
||||
func_name[len] = '\0';
|
||||
}
|
||||
func_addr = sym->n_value;
|
||||
}
|
||||
break;
|
||||
/* line number info */
|
||||
case N_SLINE:
|
||||
pc = sym->n_value + func_addr;
|
||||
if (wanted_pc >= last_pc && wanted_pc < pc)
|
||||
goto found;
|
||||
last_pc = pc;
|
||||
last_line_num = sym->n_desc;
|
||||
/* XXX: slow! */
|
||||
strcpy(last_func_name, func_name);
|
||||
break;
|
||||
/* include files */
|
||||
case N_BINCL:
|
||||
str = stab_str + sym->n_strx;
|
||||
add_incl:
|
||||
if (incl_index < INCLUDE_STACK_SIZE) {
|
||||
incl_files[incl_index++] = str;
|
||||
}
|
||||
break;
|
||||
case N_EINCL:
|
||||
if (incl_index > 1)
|
||||
incl_index--;
|
||||
break;
|
||||
case N_SO:
|
||||
if (sym->n_strx == 0) {
|
||||
incl_index = 0; /* end of translation unit */
|
||||
} else {
|
||||
str = stab_str + sym->n_strx;
|
||||
/* do not add path */
|
||||
len = strlen(str);
|
||||
if (len > 0 && str[len - 1] != '/')
|
||||
goto add_incl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
no_stabs:
|
||||
/* second pass: we try symtab symbols (no line number info) */
|
||||
incl_index = 0;
|
||||
if (symtab_section)
|
||||
{
|
||||
ElfW(Sym) *sym, *sym_end;
|
||||
int type;
|
||||
|
||||
sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
|
||||
for(sym = (ElfW(Sym) *)symtab_section->data + 1;
|
||||
sym < sym_end;
|
||||
sym++) {
|
||||
type = ELFW(ST_TYPE)(sym->st_info);
|
||||
if (type == STT_FUNC || type == STT_GNU_IFUNC) {
|
||||
if (wanted_pc >= sym->st_value &&
|
||||
wanted_pc < sym->st_value + sym->st_size) {
|
||||
pstrcpy(last_func_name, sizeof(last_func_name),
|
||||
strtab_section->data + sym->st_name);
|
||||
func_addr = sym->st_value;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* did not find any info: */
|
||||
fprintf(stderr, "%s %p ???\n", msg, (void*)wanted_pc);
|
||||
fflush(stderr);
|
||||
return 0;
|
||||
found:
|
||||
i = incl_index;
|
||||
if (i > 0)
|
||||
fprintf(stderr, "%s:%d: ", incl_files[--i], last_line_num);
|
||||
fprintf(stderr, "%s %p", msg, (void*)wanted_pc);
|
||||
if (last_func_name[0] != '\0')
|
||||
fprintf(stderr, " %s()", last_func_name);
|
||||
if (--i >= 0) {
|
||||
fprintf(stderr, " (included from ");
|
||||
for (;;) {
|
||||
fprintf(stderr, "%s", incl_files[i]);
|
||||
if (--i < 0)
|
||||
break;
|
||||
fprintf(stderr, ", ");
|
||||
}
|
||||
fprintf(stderr, ")");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
return func_addr;
|
||||
}
|
||||
|
||||
/* emit a run time error at position 'pc' */
|
||||
static void rt_error(ucontext_t *uc, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
addr_t pc;
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "Runtime error: ");
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
for(i=0;i<rt_num_callers;i++) {
|
||||
if (rt_get_caller_pc(&pc, uc, i) < 0)
|
||||
break;
|
||||
pc = rt_printline(pc, i ? "by" : "at");
|
||||
if (pc == (addr_t)rt_prog_main && pc)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifndef _WIN32
|
||||
|
||||
/* signal handler for fatal errors */
|
||||
static void sig_error(int signum, siginfo_t *siginf, void *puc)
|
||||
{
|
||||
ucontext_t *uc = puc;
|
||||
|
||||
switch(signum) {
|
||||
case SIGFPE:
|
||||
switch(siginf->si_code) {
|
||||
case FPE_INTDIV:
|
||||
case FPE_FLTDIV:
|
||||
rt_error(uc, "division by zero");
|
||||
break;
|
||||
default:
|
||||
rt_error(uc, "floating point exception");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SIGBUS:
|
||||
case SIGSEGV:
|
||||
if (rt_bound_error_msg && *rt_bound_error_msg)
|
||||
rt_error(uc, *rt_bound_error_msg);
|
||||
else
|
||||
rt_error(uc, "dereferencing invalid pointer");
|
||||
break;
|
||||
case SIGILL:
|
||||
rt_error(uc, "illegal instruction");
|
||||
break;
|
||||
case SIGABRT:
|
||||
rt_error(uc, "abort() called");
|
||||
break;
|
||||
default:
|
||||
rt_error(uc, "caught signal %d", signum);
|
||||
break;
|
||||
}
|
||||
exit(255);
|
||||
}
|
||||
|
||||
#ifndef SA_SIGINFO
|
||||
# define SA_SIGINFO 0x00000004u
|
||||
#endif
|
||||
|
||||
/* Generate a stack backtrace when a CPU exception occurs. */
|
||||
static void set_exception_handler(void)
|
||||
{
|
||||
struct sigaction sigact;
|
||||
/* install TCC signal handlers to print debug info on fatal
|
||||
runtime errors */
|
||||
sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
|
||||
sigact.sa_sigaction = sig_error;
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigaction(SIGFPE, &sigact, NULL);
|
||||
sigaction(SIGILL, &sigact, NULL);
|
||||
sigaction(SIGSEGV, &sigact, NULL);
|
||||
sigaction(SIGBUS, &sigact, NULL);
|
||||
sigaction(SIGABRT, &sigact, NULL);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifdef __i386__
|
||||
|
||||
/* fix for glibc 2.1 */
|
||||
#ifndef REG_EIP
|
||||
#define REG_EIP EIP
|
||||
#define REG_EBP EBP
|
||||
#endif
|
||||
|
||||
/* return the PC at frame level 'level'. Return negative if not found */
|
||||
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
|
||||
{
|
||||
addr_t fp;
|
||||
int i;
|
||||
|
||||
if (level == 0) {
|
||||
#if defined(__APPLE__)
|
||||
*paddr = uc->uc_mcontext->__ss.__eip;
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
*paddr = uc->uc_mcontext.mc_eip;
|
||||
#elif defined(__dietlibc__)
|
||||
*paddr = uc->uc_mcontext.eip;
|
||||
#else
|
||||
*paddr = uc->uc_mcontext.gregs[REG_EIP];
|
||||
#endif
|
||||
return 0;
|
||||
} else {
|
||||
#if defined(__APPLE__)
|
||||
fp = uc->uc_mcontext->__ss.__ebp;
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
fp = uc->uc_mcontext.mc_ebp;
|
||||
#elif defined(__dietlibc__)
|
||||
fp = uc->uc_mcontext.ebp;
|
||||
#else
|
||||
fp = uc->uc_mcontext.gregs[REG_EBP];
|
||||
#endif
|
||||
for(i=1;i<level;i++) {
|
||||
/* XXX: check address validity with program info */
|
||||
if (fp <= 0x1000 || fp >= 0xc0000000)
|
||||
return -1;
|
||||
fp = ((addr_t *)fp)[0];
|
||||
}
|
||||
*paddr = ((addr_t *)fp)[1];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#elif defined(__x86_64__)
|
||||
|
||||
/* return the PC at frame level 'level'. Return negative if not found */
|
||||
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
|
||||
{
|
||||
addr_t fp;
|
||||
int i;
|
||||
|
||||
if (level == 0) {
|
||||
/* XXX: only support linux */
|
||||
#if defined(__APPLE__)
|
||||
*paddr = uc->uc_mcontext->__ss.__rip;
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
*paddr = uc->uc_mcontext.mc_rip;
|
||||
#else
|
||||
*paddr = uc->uc_mcontext.gregs[REG_RIP];
|
||||
#endif
|
||||
return 0;
|
||||
} else {
|
||||
#if defined(__APPLE__)
|
||||
fp = uc->uc_mcontext->__ss.__rbp;
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
fp = uc->uc_mcontext.mc_rbp;
|
||||
#else
|
||||
fp = uc->uc_mcontext.gregs[REG_RBP];
|
||||
#endif
|
||||
for(i=1;i<level;i++) {
|
||||
/* XXX: check address validity with program info */
|
||||
if (fp <= 0x1000)
|
||||
return -1;
|
||||
fp = ((addr_t *)fp)[0];
|
||||
}
|
||||
*paddr = ((addr_t *)fp)[1];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#elif defined(__arm__)
|
||||
|
||||
/* return the PC at frame level 'level'. Return negative if not found */
|
||||
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
|
||||
{
|
||||
addr_t fp, sp;
|
||||
int i;
|
||||
|
||||
if (level == 0) {
|
||||
/* XXX: only supports linux */
|
||||
#if defined(__linux__)
|
||||
*paddr = uc->uc_mcontext.arm_pc;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
return 0;
|
||||
} else {
|
||||
#if defined(__linux__)
|
||||
fp = uc->uc_mcontext.arm_fp;
|
||||
sp = uc->uc_mcontext.arm_sp;
|
||||
if (sp < 0x1000)
|
||||
sp = 0x1000;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
/* XXX: specific to tinycc stack frames */
|
||||
if (fp < sp + 12 || fp & 3)
|
||||
return -1;
|
||||
for(i = 1; i < level; i++) {
|
||||
sp = ((addr_t *)fp)[-2];
|
||||
if (sp < fp || sp - fp > 16 || sp & 3)
|
||||
return -1;
|
||||
fp = ((addr_t *)fp)[-3];
|
||||
if (fp <= sp || fp - sp < 12 || fp & 3)
|
||||
return -1;
|
||||
}
|
||||
/* XXX: check address validity with program info */
|
||||
*paddr = ((addr_t *)fp)[-1];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#else
|
||||
|
||||
#warning add arch specific rt_get_caller_pc()
|
||||
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* !__i386__ */
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#else /* WIN32 */
|
||||
|
||||
static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info)
|
||||
{
|
||||
EXCEPTION_RECORD *er = ex_info->ExceptionRecord;
|
||||
CONTEXT *uc = ex_info->ContextRecord;
|
||||
switch (er->ExceptionCode) {
|
||||
case EXCEPTION_ACCESS_VIOLATION:
|
||||
if (rt_bound_error_msg && *rt_bound_error_msg)
|
||||
rt_error(uc, *rt_bound_error_msg);
|
||||
else
|
||||
rt_error(uc, "access violation");
|
||||
break;
|
||||
case EXCEPTION_STACK_OVERFLOW:
|
||||
rt_error(uc, "stack overflow");
|
||||
break;
|
||||
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||
rt_error(uc, "division by zero");
|
||||
break;
|
||||
default:
|
||||
rt_error(uc, "exception caught");
|
||||
break;
|
||||
}
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
/* Generate a stack backtrace when a CPU exception occurs. */
|
||||
static void set_exception_handler(void)
|
||||
{
|
||||
SetUnhandledExceptionFilter(cpu_exception_handler);
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
static void win64_add_function_table(TCCState *s1)
|
||||
{
|
||||
RtlAddFunctionTable(
|
||||
(RUNTIME_FUNCTION*)s1->uw_pdata->sh_addr,
|
||||
s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),
|
||||
text_section->sh_addr
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* return the PC at frame level 'level'. Return non zero if not found */
|
||||
static int rt_get_caller_pc(addr_t *paddr, CONTEXT *uc, int level)
|
||||
{
|
||||
addr_t fp, pc;
|
||||
int i;
|
||||
#ifdef _WIN64
|
||||
pc = uc->Rip;
|
||||
fp = uc->Rbp;
|
||||
#else
|
||||
pc = uc->Eip;
|
||||
fp = uc->Ebp;
|
||||
#endif
|
||||
if (level > 0) {
|
||||
for(i=1;i<level;i++) {
|
||||
/* XXX: check address validity with program info */
|
||||
if (fp <= 0x1000 || fp >= 0xc0000000)
|
||||
return -1;
|
||||
fp = ((addr_t*)fp)[0];
|
||||
}
|
||||
pc = ((addr_t*)fp)[1];
|
||||
}
|
||||
*paddr = pc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
#endif /* CONFIG_TCC_BACKTRACE */
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifdef CONFIG_TCC_STATIC
|
||||
|
||||
/* dummy function for profiling */
|
||||
ST_FUNC void *dlopen(const char *filename, int flag)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ST_FUNC void dlclose(void *p)
|
||||
{
|
||||
}
|
||||
|
||||
ST_FUNC const char *dlerror(void)
|
||||
{
|
||||
return "error";
|
||||
}
|
||||
|
||||
typedef struct TCCSyms {
|
||||
char *str;
|
||||
void *ptr;
|
||||
} TCCSyms;
|
||||
|
||||
|
||||
/* add the symbol you want here if no dynamic linking is done */
|
||||
static TCCSyms tcc_syms[] = {
|
||||
#if !defined(CONFIG_TCCBOOT)
|
||||
#define TCCSYM(a) { #a, &a, },
|
||||
TCCSYM(printf)
|
||||
TCCSYM(fprintf)
|
||||
TCCSYM(fopen)
|
||||
TCCSYM(fclose)
|
||||
#undef TCCSYM
|
||||
#endif
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
ST_FUNC void *resolve_sym(TCCState *s1, const char *symbol)
|
||||
{
|
||||
TCCSyms *p;
|
||||
p = tcc_syms;
|
||||
while (p->str != NULL) {
|
||||
if (!strcmp(p->str, symbol))
|
||||
return p->ptr;
|
||||
p++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#elif !defined(_WIN32)
|
||||
|
||||
ST_FUNC void *resolve_sym(TCCState *s1, const char *sym)
|
||||
{
|
||||
return dlsym(RTLD_DEFAULT, sym);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_TCC_STATIC */
|
||||
#endif /* TCC_IS_NATIVE */
|
||||
/* ------------------------------------------------------------- */
|
||||
261
tcctok.h
261
tcctok.h
@@ -81,10 +81,15 @@
|
||||
DEF(TOK___TIME__, "__TIME__")
|
||||
DEF(TOK___FUNCTION__, "__FUNCTION__")
|
||||
DEF(TOK___VA_ARGS__, "__VA_ARGS__")
|
||||
|
||||
|
||||
/* special identifiers */
|
||||
DEF(TOK___FUNC__, "__func__")
|
||||
|
||||
|
||||
/* special floating point values */
|
||||
DEF(TOK___NAN__, "__nan__")
|
||||
DEF(TOK___SNAN__, "__snan__")
|
||||
DEF(TOK___INF__, "__inf__")
|
||||
|
||||
/* attribute identifiers */
|
||||
/* XXX: handle all tokens generically since speed is not critical */
|
||||
DEF(TOK_SECTION1, "section")
|
||||
@@ -93,6 +98,10 @@
|
||||
DEF(TOK_ALIGNED2, "__aligned__")
|
||||
DEF(TOK_PACKED1, "packed")
|
||||
DEF(TOK_PACKED2, "__packed__")
|
||||
DEF(TOK_WEAK1, "weak")
|
||||
DEF(TOK_WEAK2, "__weak__")
|
||||
DEF(TOK_ALIAS1, "alias")
|
||||
DEF(TOK_ALIAS2, "__alias__")
|
||||
DEF(TOK_UNUSED1, "unused")
|
||||
DEF(TOK_UNUSED2, "__unused__")
|
||||
DEF(TOK_CDECL1, "cdecl")
|
||||
@@ -104,24 +113,26 @@
|
||||
DEF(TOK_FASTCALL1, "fastcall")
|
||||
DEF(TOK_FASTCALL2, "__fastcall")
|
||||
DEF(TOK_FASTCALL3, "__fastcall__")
|
||||
DEF(TOK_MODE, "__mode__")
|
||||
DEF(TOK_MODE_DI, "__DI__")
|
||||
DEF(TOK_MODE_HI, "__HI__")
|
||||
DEF(TOK_MODE_SI, "__SI__")
|
||||
DEF(TOK_DLLEXPORT, "dllexport")
|
||||
DEF(TOK_DLLIMPORT, "dllimport")
|
||||
DEF(TOK_NORETURN1, "noreturn")
|
||||
DEF(TOK_NORETURN2, "__noreturn__")
|
||||
DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
|
||||
DEF(TOK_builtin_constant_p, "__builtin_constant_p")
|
||||
DEF(TOK_builtin_frame_address, "__builtin_frame_address")
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
DEF(TOK_builtin_malloc, "__builtin_malloc")
|
||||
DEF(TOK_builtin_free, "__builtin_free")
|
||||
DEF(TOK_malloc, "malloc")
|
||||
DEF(TOK_free, "free")
|
||||
DEF(TOK_builtin_va_arg_types, "__builtin_va_arg_types")
|
||||
#endif
|
||||
DEF(TOK_REGPARM1, "regparm")
|
||||
DEF(TOK_REGPARM2, "__regparm__")
|
||||
|
||||
/* pragma */
|
||||
DEF(TOK_pack, "pack")
|
||||
#if !defined(TCC_TARGET_I386)
|
||||
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64)
|
||||
/* already defined for assembler */
|
||||
DEF(TOK_ASM_push, "push")
|
||||
DEF(TOK_ASM_pop, "pop")
|
||||
@@ -218,7 +229,7 @@
|
||||
DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
|
||||
DEF(TOK___bound_local_new, "__bound_local_new")
|
||||
DEF(TOK___bound_local_delete, "__bound_local_delete")
|
||||
#if 0
|
||||
#ifdef TCC_TARGET_PE
|
||||
DEF(TOK_malloc, "malloc")
|
||||
DEF(TOK_free, "free")
|
||||
DEF(TOK_realloc, "realloc")
|
||||
@@ -228,20 +239,26 @@
|
||||
DEF(TOK_memmove, "memmove")
|
||||
DEF(TOK_strlen, "strlen")
|
||||
DEF(TOK_strcpy, "strcpy")
|
||||
#endif
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
DEF(TOK_alloca, "alloca")
|
||||
#endif
|
||||
|
||||
/* Tiny Assembler */
|
||||
|
||||
DEF_ASM(byte)
|
||||
DEF_ASM(word)
|
||||
DEF_ASM(align)
|
||||
DEF_ASM(skip)
|
||||
DEF_ASM(space)
|
||||
DEF_ASM(string)
|
||||
DEF_ASM(asciz)
|
||||
DEF_ASM(ascii)
|
||||
DEF_ASM(file)
|
||||
DEF_ASM(globl)
|
||||
DEF_ASM(global)
|
||||
DEF_ASM(ident)
|
||||
DEF_ASM(size)
|
||||
DEF_ASM(type)
|
||||
DEF_ASM(text)
|
||||
DEF_ASM(data)
|
||||
DEF_ASM(bss)
|
||||
@@ -249,221 +266,13 @@
|
||||
DEF_ASM(fill)
|
||||
DEF_ASM(org)
|
||||
DEF_ASM(quad)
|
||||
|
||||
#ifdef TCC_TARGET_I386
|
||||
|
||||
/* WARNING: relative order of tokens is important. */
|
||||
DEF_ASM(al)
|
||||
DEF_ASM(cl)
|
||||
DEF_ASM(dl)
|
||||
DEF_ASM(bl)
|
||||
DEF_ASM(ah)
|
||||
DEF_ASM(ch)
|
||||
DEF_ASM(dh)
|
||||
DEF_ASM(bh)
|
||||
DEF_ASM(ax)
|
||||
DEF_ASM(cx)
|
||||
DEF_ASM(dx)
|
||||
DEF_ASM(bx)
|
||||
DEF_ASM(sp)
|
||||
DEF_ASM(bp)
|
||||
DEF_ASM(si)
|
||||
DEF_ASM(di)
|
||||
DEF_ASM(eax)
|
||||
DEF_ASM(ecx)
|
||||
DEF_ASM(edx)
|
||||
DEF_ASM(ebx)
|
||||
DEF_ASM(esp)
|
||||
DEF_ASM(ebp)
|
||||
DEF_ASM(esi)
|
||||
DEF_ASM(edi)
|
||||
DEF_ASM(mm0)
|
||||
DEF_ASM(mm1)
|
||||
DEF_ASM(mm2)
|
||||
DEF_ASM(mm3)
|
||||
DEF_ASM(mm4)
|
||||
DEF_ASM(mm5)
|
||||
DEF_ASM(mm6)
|
||||
DEF_ASM(mm7)
|
||||
DEF_ASM(xmm0)
|
||||
DEF_ASM(xmm1)
|
||||
DEF_ASM(xmm2)
|
||||
DEF_ASM(xmm3)
|
||||
DEF_ASM(xmm4)
|
||||
DEF_ASM(xmm5)
|
||||
DEF_ASM(xmm6)
|
||||
DEF_ASM(xmm7)
|
||||
DEF_ASM(cr0)
|
||||
DEF_ASM(cr1)
|
||||
DEF_ASM(cr2)
|
||||
DEF_ASM(cr3)
|
||||
DEF_ASM(cr4)
|
||||
DEF_ASM(cr5)
|
||||
DEF_ASM(cr6)
|
||||
DEF_ASM(cr7)
|
||||
DEF_ASM(tr0)
|
||||
DEF_ASM(tr1)
|
||||
DEF_ASM(tr2)
|
||||
DEF_ASM(tr3)
|
||||
DEF_ASM(tr4)
|
||||
DEF_ASM(tr5)
|
||||
DEF_ASM(tr6)
|
||||
DEF_ASM(tr7)
|
||||
DEF_ASM(db0)
|
||||
DEF_ASM(db1)
|
||||
DEF_ASM(db2)
|
||||
DEF_ASM(db3)
|
||||
DEF_ASM(db4)
|
||||
DEF_ASM(db5)
|
||||
DEF_ASM(db6)
|
||||
DEF_ASM(db7)
|
||||
DEF_ASM(dr0)
|
||||
DEF_ASM(dr1)
|
||||
DEF_ASM(dr2)
|
||||
DEF_ASM(dr3)
|
||||
DEF_ASM(dr4)
|
||||
DEF_ASM(dr5)
|
||||
DEF_ASM(dr6)
|
||||
DEF_ASM(dr7)
|
||||
DEF_ASM(es)
|
||||
DEF_ASM(cs)
|
||||
DEF_ASM(ss)
|
||||
DEF_ASM(ds)
|
||||
DEF_ASM(fs)
|
||||
DEF_ASM(gs)
|
||||
DEF_ASM(st)
|
||||
|
||||
DEF_BWL(mov)
|
||||
|
||||
/* generic two operands */
|
||||
DEF_BWL(add)
|
||||
DEF_BWL(or)
|
||||
DEF_BWL(adc)
|
||||
DEF_BWL(sbb)
|
||||
DEF_BWL(and)
|
||||
DEF_BWL(sub)
|
||||
DEF_BWL(xor)
|
||||
DEF_BWL(cmp)
|
||||
|
||||
/* unary ops */
|
||||
DEF_BWL(inc)
|
||||
DEF_BWL(dec)
|
||||
DEF_BWL(not)
|
||||
DEF_BWL(neg)
|
||||
DEF_BWL(mul)
|
||||
DEF_BWL(imul)
|
||||
DEF_BWL(div)
|
||||
DEF_BWL(idiv)
|
||||
|
||||
DEF_BWL(xchg)
|
||||
DEF_BWL(test)
|
||||
|
||||
/* shifts */
|
||||
DEF_BWL(rol)
|
||||
DEF_BWL(ror)
|
||||
DEF_BWL(rcl)
|
||||
DEF_BWL(rcr)
|
||||
DEF_BWL(shl)
|
||||
DEF_BWL(shr)
|
||||
DEF_BWL(sar)
|
||||
|
||||
DEF_ASM(shldw)
|
||||
DEF_ASM(shldl)
|
||||
DEF_ASM(shld)
|
||||
DEF_ASM(shrdw)
|
||||
DEF_ASM(shrdl)
|
||||
DEF_ASM(shrd)
|
||||
|
||||
DEF_ASM(pushw)
|
||||
DEF_ASM(pushl)
|
||||
DEF_ASM(push)
|
||||
DEF_ASM(popw)
|
||||
DEF_ASM(popl)
|
||||
DEF_ASM(pop)
|
||||
DEF_BWL(in)
|
||||
DEF_BWL(out)
|
||||
|
||||
DEF_WL(movzb)
|
||||
|
||||
DEF_ASM(movzwl)
|
||||
DEF_ASM(movsbw)
|
||||
DEF_ASM(movsbl)
|
||||
DEF_ASM(movswl)
|
||||
|
||||
DEF_WL(lea)
|
||||
|
||||
DEF_ASM(les)
|
||||
DEF_ASM(lds)
|
||||
DEF_ASM(lss)
|
||||
DEF_ASM(lfs)
|
||||
DEF_ASM(lgs)
|
||||
|
||||
DEF_ASM(call)
|
||||
DEF_ASM(jmp)
|
||||
DEF_ASM(lcall)
|
||||
DEF_ASM(ljmp)
|
||||
|
||||
DEF_ASMTEST(j)
|
||||
|
||||
DEF_ASMTEST(set)
|
||||
DEF_ASMTEST(cmov)
|
||||
|
||||
DEF_WL(bsf)
|
||||
DEF_WL(bsr)
|
||||
DEF_WL(bt)
|
||||
DEF_WL(bts)
|
||||
DEF_WL(btr)
|
||||
DEF_WL(btc)
|
||||
|
||||
DEF_WL(lsl)
|
||||
|
||||
/* generic FP ops */
|
||||
DEF_FP(add)
|
||||
DEF_FP(mul)
|
||||
|
||||
DEF_ASM(fcom)
|
||||
DEF_ASM(fcom_1) /* non existant op, just to have a regular table */
|
||||
DEF_FP1(com)
|
||||
|
||||
DEF_FP(comp)
|
||||
DEF_FP(sub)
|
||||
DEF_FP(subr)
|
||||
DEF_FP(div)
|
||||
DEF_FP(divr)
|
||||
|
||||
DEF_BWL(xadd)
|
||||
DEF_BWL(cmpxchg)
|
||||
|
||||
/* string ops */
|
||||
DEF_BWL(cmps)
|
||||
DEF_BWL(scmp)
|
||||
DEF_BWL(ins)
|
||||
DEF_BWL(outs)
|
||||
DEF_BWL(lods)
|
||||
DEF_BWL(slod)
|
||||
DEF_BWL(movs)
|
||||
DEF_BWL(smov)
|
||||
DEF_BWL(scas)
|
||||
DEF_BWL(ssca)
|
||||
DEF_BWL(stos)
|
||||
DEF_BWL(ssto)
|
||||
|
||||
/* generic asm ops */
|
||||
|
||||
#define ALT(x)
|
||||
#define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
|
||||
#define DEF_ASM_OP0L(name, opcode, group, instr_type)
|
||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
||||
#include "i386-asm.h"
|
||||
|
||||
#define ALT(x)
|
||||
#define DEF_ASM_OP0(name, opcode)
|
||||
#define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
|
||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
|
||||
#include "i386-asm.h"
|
||||
|
||||
#if defined(TCC_TARGET_I386)
|
||||
DEF_ASM(code16)
|
||||
DEF_ASM(code32)
|
||||
#elif defined(TCC_TARGET_X86_64)
|
||||
DEF_ASM(code64)
|
||||
#endif
|
||||
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
#include "i386-tok.h"
|
||||
#endif
|
||||
|
||||
150
tests/Makefile
150
tests/Makefile
@@ -2,43 +2,86 @@
|
||||
# Tiny C Compiler Makefile - tests
|
||||
#
|
||||
|
||||
# what tests to run
|
||||
TESTS = libtest test3
|
||||
|
||||
# these should work too
|
||||
# TESTS += test1 test2 speed
|
||||
|
||||
# these don't work as they should
|
||||
# TESTS += test4 btest asmtest
|
||||
|
||||
|
||||
TOP = ..
|
||||
include $(TOP)/Makefile
|
||||
VPATH = $(top_srcdir)/tests
|
||||
|
||||
# what tests to run
|
||||
TESTS = \
|
||||
hello-exe \
|
||||
hello-run \
|
||||
libtest \
|
||||
test3 \
|
||||
moretests
|
||||
|
||||
# test4 -- problem with -static
|
||||
# asmtest -- minor differences with gcc
|
||||
# btest -- works on i386 (including win32)
|
||||
# test3 -- win32 does not know how to printf long doubles
|
||||
|
||||
# bounds-checking is supported only on i386
|
||||
ifneq ($(ARCH),i386)
|
||||
TESTS := $(filter-out btest,$(TESTS))
|
||||
endif
|
||||
ifdef CONFIG_WIN32
|
||||
TESTS := $(filter-out test3,$(TESTS))
|
||||
endif
|
||||
ifeq ($(TARGETOS),Darwin)
|
||||
TESTS := $(filter-out hello-exe test3 btest,$(TESTS))
|
||||
endif
|
||||
|
||||
ifdef DISABLE_STATIC
|
||||
export LD_LIBRARY_PATH:=$(CURDIR)/..
|
||||
endif
|
||||
|
||||
ifeq ($(TARGETOS),Darwin)
|
||||
CFLAGS+=-Wl,-flat_namespace,-undefined,warning
|
||||
export MACOSX_DEPLOYMENT_TARGET:=10.2
|
||||
NATIVE_DEFINES+=-D_ANSI_SOURCE
|
||||
endif
|
||||
|
||||
# run local version of tcc with local libraries and includes
|
||||
TCC = ../tcc -B..
|
||||
RUN_TCC = $(NATIVE_TARGET) -run ../tcc.c -B..
|
||||
DISAS=objdump -d
|
||||
TCCFLAGS = -B$(TOP)
|
||||
ifdef CONFIG_WIN32
|
||||
TCCFLAGS = -B$(top_srcdir)/win32 -I$(top_srcdir)/include -L$(TOP)
|
||||
endif
|
||||
|
||||
TCC = $(TOP)/tcc $(TCCFLAGS)
|
||||
RUN_TCC = $(NATIVE_DEFINES) -DONE_SOURCE -run $(TOP)/tcc.c $(TCCFLAGS)
|
||||
|
||||
DISAS = objdump -d
|
||||
|
||||
# libtcc test
|
||||
ifdef LIBTCC1
|
||||
LIBTCC1:=$(TOP)/$(LIBTCC1)
|
||||
endif
|
||||
|
||||
all test : $(TESTS)
|
||||
|
||||
# make sure that tcc exists
|
||||
$(TESTS) : ../tcc
|
||||
../tcc ../libtcc.a :
|
||||
$(MAKE) -C ..
|
||||
|
||||
# libtcc test
|
||||
libtest: libtcc_test$(EXESUF)
|
||||
hello-exe: ../examples/ex1.c
|
||||
@echo ------------ $@ ------------
|
||||
./libtcc_test lib_path=..
|
||||
$(TCC) $< -o hello$(EXESUF) || ($(TOP)/tcc -vv; exit 1) && ./hello$(EXESUF)
|
||||
|
||||
libtcc_test$(EXESUF): libtcc_test.c ../libtcc.a
|
||||
$(CC) -o $@ $^ -I.. $(CFLAGS) $(LIBS)
|
||||
hello-run: ../examples/ex1.c
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) -run $<
|
||||
|
||||
libtest: libtcc_test$(EXESUF) $(LIBTCC1)
|
||||
@echo ------------ $@ ------------
|
||||
./libtcc_test$(EXESUF) lib_path=..
|
||||
|
||||
libtcc_test$(EXESUF): libtcc_test.c $(top_builddir)/$(LIBTCC)
|
||||
$(CC) -o $@ $^ $(CPPFLAGS) $(CFLAGS) $(NATIVE_DEFINES) $(LIBS) $(LINK_LIBTCC) $(LDFLAGS)
|
||||
|
||||
moretests:
|
||||
@echo ------------ $@ ------------
|
||||
$(MAKE) -C tests2
|
||||
|
||||
# test.ref - generate using gcc
|
||||
# copy only tcclib.h so GCC's stddef and stdarg will be used
|
||||
test.ref: tcctest.c
|
||||
cp -u ../include/tcclib.h .
|
||||
$(CC) -o tcctest.gcc $< -I. -w $(CFLAGS)
|
||||
cp ../include/tcclib.h .
|
||||
gcc -o tcctest.gcc $< -I. $(CPPFLAGS) -w $(CFLAGS) $(NATIVE_DEFINES) -std=gnu99 -O0 -fno-omit-frame-pointer $(LDFLAGS)
|
||||
./tcctest.gcc > $@
|
||||
|
||||
# auto test
|
||||
@@ -62,66 +105,75 @@ test3: test.ref
|
||||
# binary output test
|
||||
test4: test.ref
|
||||
@echo ------------ $@ ------------
|
||||
# dynamic output
|
||||
$(TCC) -o tcctest1 tcctest.c
|
||||
./tcctest1 > test1.out
|
||||
@if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi
|
||||
# object + link output
|
||||
$(TCC) -c -o tcctest3.o tcctest.c
|
||||
$(TCC) -o tcctest3 tcctest3.o
|
||||
./tcctest3 > test3.out
|
||||
@if diff -u test.ref test3.out ; then echo "Object Auto Test OK"; fi
|
||||
# static output
|
||||
$(TCC) -static -o tcctest2 tcctest.c
|
||||
./tcctest2 > test2.out
|
||||
@if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi
|
||||
# dynamic output
|
||||
$(TCC) -o tcctest1 tcctest.c
|
||||
./tcctest1 > test1.out
|
||||
@if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi
|
||||
# dynamic output + bound check
|
||||
$(TCC) -b -o tcctest4 tcctest.c
|
||||
./tcctest4 > test4.out
|
||||
@if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi
|
||||
# static output
|
||||
$(TCC) -static -o tcctest2 tcctest.c
|
||||
./tcctest2 > test2.out
|
||||
@if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi
|
||||
|
||||
# memory and bound check auto test
|
||||
BOUNDS_OK = 1 4 8 10
|
||||
BOUNDS_FAIL= 2 5 7 9 11 12 13
|
||||
BOUNDS_OK = 1 4 8 10 14
|
||||
BOUNDS_FAIL= 2 5 7 9 11 12 13 15
|
||||
|
||||
btest: boundtest.c
|
||||
@echo ------------ $@ ------------
|
||||
@for i in $(BOUNDS_OK); do \
|
||||
echo ; echo --- boundtest $$i ---; \
|
||||
if $(TCC) -b -run boundtest.c $$i ; then \
|
||||
/bin/true ; \
|
||||
echo succeded as expected; \
|
||||
else\
|
||||
echo Failed positive test $$i ; exit 1 ; \
|
||||
fi ;\
|
||||
done ;\
|
||||
for i in $(BOUNDS_FAIL); do \
|
||||
echo ; echo --- boundtest $$i ---; \
|
||||
if $(TCC) -b -run boundtest.c $$i ; then \
|
||||
echo Failed negative test $$i ; exit 1 ;\
|
||||
else\
|
||||
/bin/true ; \
|
||||
echo failed as expected; \
|
||||
fi ;\
|
||||
done ;\
|
||||
echo Bound test OK
|
||||
echo; echo Bound test OK
|
||||
|
||||
# speed test
|
||||
speed: ex2 ex3
|
||||
speedtest: ex2 ex3
|
||||
@echo ------------ $@ ------------
|
||||
time ./ex2 1238 2 3 4 10 13 4
|
||||
time $(TCC) -run ../examples/ex2.c 1238 2 3 4 10 13 4
|
||||
time $(TCC) -run $(top_srcdir)/examples/ex2.c 1238 2 3 4 10 13 4
|
||||
time ./ex3 35
|
||||
time $(TCC) -run ../examples/ex3.c 35
|
||||
time $(TCC) -run $(top_srcdir)/examples/ex3.c 35
|
||||
|
||||
ex%: ../examples/ex%.c
|
||||
$(CC) -o $@ $< $(CFLAGS)
|
||||
weaktest: test.ref
|
||||
$(TCC) -c tcctest.c -o weaktest.tcc.o $(CPPFLAGS) $(CFLAGS)
|
||||
$(CC) -c tcctest.c -o weaktest.gcc.o -I. $(CPPFLAGS) -w $(CFLAGS)
|
||||
objdump -t weaktest.tcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.tcc.o.txt
|
||||
objdump -t weaktest.gcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.gcc.o.txt
|
||||
diff weaktest.gcc.o.txt weaktest.tcc.o.txt && echo "Weak Auto Test OK"
|
||||
|
||||
ex%: $(top_srcdir)/examples/ex%.c
|
||||
$(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
# tiny assembler testing
|
||||
asmtest.ref: asmtest.S
|
||||
$(CC) -o asmtest.ref.o -c asmtest.S
|
||||
objdump -D asmtest.ref.o > $@
|
||||
$(CC) -Wa,-W -o asmtest.ref.o -c asmtest.S
|
||||
objdump -D asmtest.ref.o > asmtest.ref
|
||||
|
||||
asmtest: asmtest.ref
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) -c asmtest.S
|
||||
objdump -D asmtest.o > $@
|
||||
objdump -D asmtest.o > asmtest.out
|
||||
@if diff -u --ignore-matching-lines="file format" asmtest.ref asmtest.out ; then echo "ASM Auto Test OK"; fi
|
||||
|
||||
# targets for development
|
||||
@@ -141,5 +193,7 @@ cache: tcc_g
|
||||
|
||||
# clean
|
||||
clean:
|
||||
rm -vf *~ *.o *.a *.bin *.i *.ref *.out *.out? *.gcc \
|
||||
tcctest[1234] ex? libtcc_test$(EXESUF) tcc_g tcclib.h
|
||||
$(MAKE) -C tests2 $@
|
||||
rm -vf *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.gcc *.exe \
|
||||
hello libtcc_test tcctest[1234] ex? tcc_g tcclib.h
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# gas comment with ``gnu'' style quotes
|
||||
|
||||
/* some directive tests */
|
||||
|
||||
@@ -9,7 +10,8 @@
|
||||
.int 1, 2, 3
|
||||
.align 8
|
||||
.byte 1
|
||||
.align 16, 0x90
|
||||
/* .align 16, 0x90 gas is too clever for us with 0x90 fill */
|
||||
.align 16, 0x91 /* 0x91 tests the non-clever behaviour */
|
||||
.skip 3
|
||||
.skip 15, 0x90
|
||||
.string "hello\0world"
|
||||
@@ -121,6 +123,7 @@ addl $0x123, 0x100
|
||||
addl $0x123, 0x100(%ebx)
|
||||
addl $0x123, 0x100(%ebx,%edx,2)
|
||||
addl $0x123, 0x100(%esp)
|
||||
addl $0x123, (3*8)(%esp)
|
||||
addl $0x123, (%ebp)
|
||||
addl $0x123, (%esp)
|
||||
cmpl $0x123, (%esp)
|
||||
@@ -196,6 +199,11 @@ call *%eax
|
||||
call *0x1000
|
||||
call func1
|
||||
|
||||
.global L5,L6
|
||||
|
||||
L5:
|
||||
L6:
|
||||
|
||||
lcall $0x100, $0x1000
|
||||
|
||||
jmp 0x1000
|
||||
@@ -205,8 +213,10 @@ jmp *0x1000
|
||||
ljmp $0x100, $0x1000
|
||||
|
||||
ret
|
||||
retl
|
||||
|
||||
ret $10
|
||||
retl $10
|
||||
|
||||
lret
|
||||
|
||||
@@ -240,8 +250,12 @@ L3:
|
||||
|
||||
fadd
|
||||
fadd %st(1), %st
|
||||
fadd %st(0), %st(1)
|
||||
fadd %st(3)
|
||||
|
||||
fmul %st(0),%st(0)
|
||||
fmul %st(0),%st(1)
|
||||
|
||||
faddp %st(5)
|
||||
faddp
|
||||
faddp %st(1), %st
|
||||
@@ -341,9 +355,9 @@ L3:
|
||||
fnstcw 0x1002
|
||||
fstcw 0x1002
|
||||
fnstsw 0x1004
|
||||
fnstsw %eax
|
||||
fnstsw (%eax)
|
||||
fstsw 0x1004
|
||||
fstsw %eax
|
||||
fstsw (%eax)
|
||||
fnclex
|
||||
fclex
|
||||
fnstenv 0x1000
|
||||
@@ -470,6 +484,24 @@ int $0x10
|
||||
repz
|
||||
repne
|
||||
repnz
|
||||
nop
|
||||
|
||||
lock ;negl (%eax)
|
||||
wait ;pushf
|
||||
rep ;stosb
|
||||
repe ;lodsb
|
||||
repz ;cmpsb
|
||||
repne;movsb
|
||||
repnz;outsb
|
||||
|
||||
/* handle one-line prefix + ops */
|
||||
lock negl (%eax)
|
||||
wait pushf
|
||||
rep stosb
|
||||
repe lodsb
|
||||
repz cmpsb
|
||||
repne movsb
|
||||
repnz outsb
|
||||
|
||||
invd
|
||||
wbinvd
|
||||
@@ -556,3 +588,22 @@ int $0x10
|
||||
pushl $1
|
||||
pushw $1
|
||||
push $1
|
||||
|
||||
#ifdef __ASSEMBLER__ // should be defined, for S files
|
||||
inc %eax
|
||||
#endif
|
||||
|
||||
ft1: ft2: ft3: ft4: ft5: ft6: ft7: ft8: ft9:
|
||||
xor %eax, %eax
|
||||
ret
|
||||
|
||||
.type ft1,STT_FUNC
|
||||
.type ft2,@STT_FUNC
|
||||
.type ft3,%STT_FUNC
|
||||
.type ft4,"STT_FUNC"
|
||||
.type ft5,function
|
||||
.type ft6,@function
|
||||
.type ft7,%function
|
||||
.type ft8,"function"
|
||||
|
||||
pause
|
||||
|
||||
@@ -169,6 +169,23 @@ int test13(void)
|
||||
return strlen(tab);
|
||||
}
|
||||
|
||||
int test14(void)
|
||||
{
|
||||
char *p = alloca(TAB_SIZE);
|
||||
memset(p, 'a', TAB_SIZE);
|
||||
p[TAB_SIZE-1] = 0;
|
||||
return strlen(p);
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test15(void)
|
||||
{
|
||||
char *p = alloca(TAB_SIZE-1);
|
||||
memset(p, 'a', TAB_SIZE);
|
||||
p[TAB_SIZE-1] = 0;
|
||||
return strlen(p);
|
||||
}
|
||||
|
||||
int (*table_test[])(void) = {
|
||||
test1,
|
||||
test1,
|
||||
@@ -184,6 +201,8 @@ int (*table_test[])(void) = {
|
||||
test11,
|
||||
test12,
|
||||
test13,
|
||||
test14,
|
||||
test15,
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
||||
@@ -8,11 +8,11 @@ nb_failed="0"
|
||||
for src in $TESTSUITE_PATH/compile/*.c ; do
|
||||
echo $TCC -o /tmp/test.o -c $src
|
||||
$TCC -o /tmp/test.o -c $src >> tcc.log 2>&1
|
||||
if [ "$?" == "0" ] ; then
|
||||
if [ "$?" = "0" ] ; then
|
||||
result="PASS"
|
||||
else
|
||||
result="FAIL"
|
||||
nb_failed=$[ $nb_failed + 1 ]
|
||||
nb_failed=$(( $nb_failed + 1 ))
|
||||
fi
|
||||
echo "$result: $src" >> tcc.sum
|
||||
done
|
||||
@@ -20,11 +20,11 @@ done
|
||||
for src in $TESTSUITE_PATH/execute/*.c ; do
|
||||
echo $TCC $src
|
||||
$TCC $src >> tcc.log 2>&1
|
||||
if [ "$?" == "0" ] ; then
|
||||
if [ "$?" = "0" ] ; then
|
||||
result="PASS"
|
||||
else
|
||||
result="FAIL"
|
||||
nb_failed=$[ $nb_failed + 1 ]
|
||||
nb_failed=$(( $nb_failed + 1 ))
|
||||
fi
|
||||
echo "$result: $src" >> tcc.sum
|
||||
done
|
||||
|
||||
@@ -36,8 +36,6 @@ int main(int argc, char **argv)
|
||||
{
|
||||
TCCState *s;
|
||||
int (*func)(int);
|
||||
void *mem;
|
||||
int size;
|
||||
|
||||
s = tcc_new();
|
||||
if (!s) {
|
||||
@@ -59,26 +57,20 @@ int main(int argc, char **argv)
|
||||
You may also open a dll with tcc_add_dll() and use symbols from that */
|
||||
tcc_add_symbol(s, "add", add);
|
||||
|
||||
/* get needed size of the code */
|
||||
size = tcc_relocate(s, NULL);
|
||||
if (size == -1)
|
||||
/* relocate the code */
|
||||
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
|
||||
return 1;
|
||||
|
||||
/* allocate memory and copy the code into it */
|
||||
mem = malloc(size);
|
||||
tcc_relocate(s, mem);
|
||||
|
||||
/* get entry symbol */
|
||||
func = tcc_get_symbol(s, "foo");
|
||||
if (!func)
|
||||
return 1;
|
||||
|
||||
/* delete the state */
|
||||
tcc_delete(s);
|
||||
|
||||
/* run the code */
|
||||
func(32);
|
||||
|
||||
free(mem);
|
||||
/* delete the state */
|
||||
tcc_delete(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
547
tests/tcctest.c
547
tests/tcctest.c
@@ -45,6 +45,7 @@
|
||||
void string_test();
|
||||
void expr_test();
|
||||
void macro_test();
|
||||
void recursive_macro_test();
|
||||
void scope_test();
|
||||
void forward_test();
|
||||
void funcptr_test();
|
||||
@@ -76,12 +77,19 @@ void whitespace_test(void);
|
||||
void relocation_test(void);
|
||||
void old_style_function(void);
|
||||
void alloca_test(void);
|
||||
void c99_vla_test(int size1, int size2);
|
||||
void sizeof_test(void);
|
||||
void typeof_test(void);
|
||||
void local_label_test(void);
|
||||
void statement_expr_test(void);
|
||||
void asm_test(void);
|
||||
void builtin_test(void);
|
||||
void weak_test(void);
|
||||
void global_data_test(void);
|
||||
void cmp_comparison_test(void);
|
||||
void math_cmp_test(void);
|
||||
void callsave_test(void);
|
||||
void builtin_frame_address_test(void);
|
||||
|
||||
int fib(int n);
|
||||
void num(int n);
|
||||
@@ -100,6 +108,10 @@ int isid(int c);
|
||||
#define HIGHLOW "hello"
|
||||
#define LOW LOW ", world"
|
||||
|
||||
static int onetwothree = 123;
|
||||
#define onetwothree4 onetwothree
|
||||
#define onetwothree xglue(onetwothree,4)
|
||||
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#ifdef C99_MACROS
|
||||
@@ -152,6 +164,8 @@ void macro_test(void)
|
||||
printf("s4=%s\n", str(a1));
|
||||
printf("B3=%d\n", B3);
|
||||
|
||||
printf("onetwothree=%d\n", onetwothree);
|
||||
|
||||
#ifdef A
|
||||
printf("A defined\n");
|
||||
#endif
|
||||
@@ -278,6 +292,38 @@ comment
|
||||
/* test function macro substitution when the function name is
|
||||
substituted */
|
||||
TEST2();
|
||||
|
||||
/* And again when the name and parenthes are separated by a
|
||||
comment. */
|
||||
TEST2 /* the comment */ ();
|
||||
}
|
||||
|
||||
|
||||
static void print_num(char *fn, int line, int num) {
|
||||
printf("fn %s, line %d, num %d\n", fn, line, num);
|
||||
}
|
||||
|
||||
void recursive_macro_test(void)
|
||||
{
|
||||
|
||||
#define ELF32_ST_TYPE(val) ((val) & 0xf)
|
||||
#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
|
||||
#define STB_WEAK 2 /* Weak symbol */
|
||||
#define ELFW(type) ELF##32##_##type
|
||||
printf("%d\n", ELFW(ST_INFO)(STB_WEAK, ELFW(ST_TYPE)(123)));
|
||||
|
||||
#define WRAP(x) x
|
||||
|
||||
#define print_num(x) print_num(__FILE__,__LINE__,x)
|
||||
print_num(123);
|
||||
WRAP(print_num(123));
|
||||
WRAP(WRAP(print_num(123)));
|
||||
|
||||
static struct recursive_macro { int rm_field; } G;
|
||||
#define rm_field (G.rm_field)
|
||||
printf("rm_field = %d\n", rm_field);
|
||||
printf("rm_field = %d\n", WRAP(rm_field));
|
||||
WRAP((printf("rm_field = %d %d\n", rm_field, WRAP(rm_field))));
|
||||
}
|
||||
|
||||
int op(a,b)
|
||||
@@ -356,6 +402,12 @@ void loop_test()
|
||||
} while (i < 10);
|
||||
printf("\n");
|
||||
|
||||
char count = 123;
|
||||
/* c99 for loop init test */
|
||||
for (size_t count = 1; count < 3; count++)
|
||||
printf("count=%d\n", count);
|
||||
printf("count = %d\n", count);
|
||||
|
||||
/* break/continue tests */
|
||||
i = 0;
|
||||
while (1) {
|
||||
@@ -388,6 +440,7 @@ void loop_test()
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
typedef int typedef_and_label;
|
||||
|
||||
void goto_test()
|
||||
{
|
||||
@@ -396,6 +449,8 @@ void goto_test()
|
||||
|
||||
printf("goto:\n");
|
||||
i = 0;
|
||||
/* This needs to parse as label, not as start of decl. */
|
||||
typedef_and_label:
|
||||
s_loop:
|
||||
if (i >= 10)
|
||||
goto s_end;
|
||||
@@ -500,6 +555,7 @@ int main(int argc, char **argv)
|
||||
string_test();
|
||||
expr_test();
|
||||
macro_test();
|
||||
recursive_macro_test();
|
||||
scope_test();
|
||||
forward_test();
|
||||
funcptr_test();
|
||||
@@ -531,12 +587,21 @@ int main(int argc, char **argv)
|
||||
relocation_test();
|
||||
old_style_function();
|
||||
alloca_test();
|
||||
c99_vla_test(5, 2);
|
||||
sizeof_test();
|
||||
typeof_test();
|
||||
statement_expr_test();
|
||||
local_label_test();
|
||||
asm_test();
|
||||
builtin_test();
|
||||
#ifndef _WIN32
|
||||
weak_test();
|
||||
#endif
|
||||
global_data_test();
|
||||
cmp_comparison_test();
|
||||
math_cmp_test();
|
||||
callsave_test();
|
||||
builtin_frame_address_test();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -569,9 +634,9 @@ void scope_test()
|
||||
printf("g5=%d\n", g);
|
||||
}
|
||||
|
||||
void array_test(int a[4])
|
||||
void array_test()
|
||||
{
|
||||
int i, j;
|
||||
int i, j, a[4];
|
||||
|
||||
printf("array:\n");
|
||||
printf("sizeof(a) = %d\n", sizeof(a));
|
||||
@@ -592,6 +657,8 @@ void array_test(int a[4])
|
||||
printf(" %3d", ((int *)tab2)[i]);
|
||||
}
|
||||
printf("\n");
|
||||
printf("sizeof(size_t)=%d\n", sizeof(size_t));
|
||||
printf("sizeof(ptrdiff_t)=%d\n", sizeof(ptrdiff_t));
|
||||
}
|
||||
|
||||
void expr_test()
|
||||
@@ -1049,6 +1116,7 @@ void num(int n)
|
||||
printf("%c", *p);
|
||||
}
|
||||
printf("\n");
|
||||
free(tab);
|
||||
}
|
||||
|
||||
/* structure assignment tests */
|
||||
@@ -1059,9 +1127,9 @@ struct structa1 {
|
||||
|
||||
struct structa1 ssta1;
|
||||
|
||||
void struct_assign_test1(struct structa1 s1, int t)
|
||||
void struct_assign_test1(struct structa1 s1, int t, float f)
|
||||
{
|
||||
printf("%d %d %d\n", s1.f1, s1.f2, t);
|
||||
printf("%d %d %d %f\n", s1.f1, s1.f2, t, f);
|
||||
}
|
||||
|
||||
struct structa1 struct_assign_test2(struct structa1 s1, int t)
|
||||
@@ -1073,25 +1141,38 @@ struct structa1 struct_assign_test2(struct structa1 s1, int t)
|
||||
|
||||
void struct_assign_test(void)
|
||||
{
|
||||
struct structa1 lsta1, lsta2;
|
||||
struct S {
|
||||
struct structa1 lsta1, lsta2;
|
||||
int i;
|
||||
} s, *ps;
|
||||
|
||||
ps = &s;
|
||||
ps->i = 4;
|
||||
#if 0
|
||||
printf("struct_assign_test:\n");
|
||||
|
||||
lsta1.f1 = 1;
|
||||
lsta1.f2 = 2;
|
||||
printf("%d %d\n", lsta1.f1, lsta1.f2);
|
||||
lsta2 = lsta1;
|
||||
printf("%d %d\n", lsta2.f1, lsta2.f2);
|
||||
s.lsta1.f1 = 1;
|
||||
s.lsta1.f2 = 2;
|
||||
printf("%d %d\n", s.lsta1.f1, s.lsta1.f2);
|
||||
s.lsta2 = s.lsta1;
|
||||
printf("%d %d\n", s.lsta2.f1, s.lsta2.f2);
|
||||
#else
|
||||
lsta2.f1 = 1;
|
||||
lsta2.f2 = 2;
|
||||
s.lsta2.f1 = 1;
|
||||
s.lsta2.f2 = 2;
|
||||
#endif
|
||||
struct_assign_test1(lsta2, 3);
|
||||
struct_assign_test1(ps->lsta2, 3, 4.5);
|
||||
|
||||
printf("before call: %d %d\n", lsta2.f1, lsta2.f2);
|
||||
lsta2 = struct_assign_test2(lsta2, 4);
|
||||
printf("after call: %d %d\n", lsta2.f1, lsta2.f2);
|
||||
printf("before call: %d %d\n", s.lsta2.f1, s.lsta2.f2);
|
||||
ps->lsta2 = struct_assign_test2(ps->lsta2, ps->i);
|
||||
printf("after call: %d %d\n", ps->lsta2.f1, ps->lsta2.f2);
|
||||
|
||||
static struct {
|
||||
void (*elem)();
|
||||
} t[] = {
|
||||
/* XXX: we should allow this even without braces */
|
||||
{ struct_assign_test }
|
||||
};
|
||||
printf("%d\n", struct_assign_test == t[0].elem);
|
||||
}
|
||||
|
||||
/* casts to short/char */
|
||||
@@ -1218,6 +1299,44 @@ int sinit18[10] = {
|
||||
[8] = 10,
|
||||
};
|
||||
|
||||
struct complexinit0 {
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
struct complexinit {
|
||||
int a;
|
||||
const struct complexinit0 *b;
|
||||
};
|
||||
|
||||
const static struct complexinit cix[] = {
|
||||
[0] = {
|
||||
.a = 2000,
|
||||
.b = (const struct complexinit0[]) {
|
||||
{ 2001, 2002 },
|
||||
{ 2003, 2003 },
|
||||
{}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct complexinit2 {
|
||||
int a;
|
||||
int b[];
|
||||
};
|
||||
|
||||
struct complexinit2 cix20;
|
||||
|
||||
struct complexinit2 cix21 = {
|
||||
.a = 3000,
|
||||
.b = { 3001, 3002, 3003 }
|
||||
};
|
||||
|
||||
struct complexinit2 cix22 = {
|
||||
.a = 4000,
|
||||
.b = { 4001, 4002, 4003, 4004, 4005, 4006 }
|
||||
};
|
||||
|
||||
void init_test(void)
|
||||
{
|
||||
int linit1 = 2;
|
||||
@@ -1310,6 +1429,14 @@ void init_test(void)
|
||||
for(i=0;i<10;i++)
|
||||
printf("%x ", sinit18[i]);
|
||||
printf("\n");
|
||||
/* complex init check */
|
||||
printf("cix: %d %d %d %d %d %d %d\n",
|
||||
cix[0].a,
|
||||
cix[0].b[0].a, cix[0].b[0].b,
|
||||
cix[0].b[1].a, cix[0].b[1].b,
|
||||
cix[0].b[2].a, cix[0].b[2].b);
|
||||
printf("cix2: %d %d\n", cix21.b[2], cix22.b[5]);
|
||||
printf("sizeof cix20 %d, cix21 %d, sizeof cix22 %d\n", sizeof cix20, sizeof cix21, sizeof cix22);
|
||||
}
|
||||
|
||||
|
||||
@@ -1358,6 +1485,8 @@ void c99_bool_test(void)
|
||||
void bitfield_test(void)
|
||||
{
|
||||
int a;
|
||||
short sa;
|
||||
unsigned char ca;
|
||||
struct sbf1 {
|
||||
int f1 : 3;
|
||||
int : 2;
|
||||
@@ -1379,6 +1508,9 @@ void bitfield_test(void)
|
||||
st1.f5++;
|
||||
printf("%d %d %d %d %d\n",
|
||||
st1.f1, st1.f2, st1.f3, st1.f4, st1.f5);
|
||||
sa = st1.f5;
|
||||
ca = st1.f5;
|
||||
printf("%d %d\n", sa, ca);
|
||||
|
||||
st1.f1 = 7;
|
||||
if (st1.f1 == -1)
|
||||
@@ -1776,14 +1908,15 @@ void manyarg_test(void)
|
||||
|
||||
void vprintf1(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_list ap, aq;
|
||||
const char *p;
|
||||
int c, i;
|
||||
double d;
|
||||
long long ll;
|
||||
long double ld;
|
||||
|
||||
va_start(ap, fmt);
|
||||
va_start(aq, fmt);
|
||||
va_copy(ap, aq);
|
||||
|
||||
p = fmt;
|
||||
for(;;) {
|
||||
@@ -1819,13 +1952,34 @@ void vprintf1(const char *fmt, ...)
|
||||
}
|
||||
}
|
||||
the_end:
|
||||
va_end(aq);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
struct myspace {
|
||||
short int profile;
|
||||
};
|
||||
|
||||
void stdarg_for_struct(struct myspace bob, ...)
|
||||
{
|
||||
struct myspace george, bill;
|
||||
va_list ap;
|
||||
short int validate;
|
||||
|
||||
va_start(ap, bob);
|
||||
bill = va_arg(ap, struct myspace);
|
||||
george = va_arg(ap, struct myspace);
|
||||
validate = va_arg(ap, int);
|
||||
printf("stdarg_for_struct: %d %d %d %d\n",
|
||||
bob.profile, bill.profile, george.profile, validate);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void stdarg_test(void)
|
||||
{
|
||||
long double ld = 1234567891234LL;
|
||||
struct myspace bob;
|
||||
|
||||
vprintf1("%d %d %d\n", 1, 2, 3);
|
||||
vprintf1("%f %d %f\n", 1.0, 2, 3.0);
|
||||
vprintf1("%l %l %d %f\n", 1234567891234LL, 987654321986LL, 3, 1234.0);
|
||||
@@ -1867,6 +2021,9 @@ void stdarg_test(void)
|
||||
0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0,
|
||||
ld, 1234567891234LL, 987654321986LL,
|
||||
42.0, 43.0, ld);
|
||||
|
||||
bob.profile = 42;
|
||||
stdarg_for_struct(bob, bob, bob, bob.profile);
|
||||
}
|
||||
|
||||
void whitespace_test(void)
|
||||
@@ -1949,6 +2106,67 @@ void alloca_test()
|
||||
/* Test alloca embedded in a larger expression */
|
||||
printf("alloca: %s\n", strcpy(alloca(strlen(demo)+1),demo) );
|
||||
#endif
|
||||
}
|
||||
|
||||
void *bounds_checking_is_enabled()
|
||||
{
|
||||
char ca[10], *cp = ca-1;
|
||||
return (ca != cp + 1) ? cp : NULL;
|
||||
}
|
||||
|
||||
typedef int constant_negative_array_size_as_compile_time_assertion_idiom[(1 ? 2 : 0) - 1];
|
||||
|
||||
void c99_vla_test(int size1, int size2)
|
||||
{
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
int size = size1 * size2;
|
||||
int tab1[size][2], tab2[10][2];
|
||||
void *tab1_ptr, *tab2_ptr, *bad_ptr;
|
||||
|
||||
/* "size" should have been 'captured' at tab1 declaration,
|
||||
so modifying it should have no effect on VLA behaviour. */
|
||||
size = size-1;
|
||||
|
||||
printf("Test C99 VLA 1 (sizeof): ");
|
||||
printf("%s\n", (sizeof tab1 == size1 * size2 * 2 * sizeof(int)) ? "PASSED" : "FAILED");
|
||||
tab1_ptr = tab1;
|
||||
tab2_ptr = tab2;
|
||||
printf("Test C99 VLA 2 (ptrs substract): ");
|
||||
printf("%s\n", (tab2 - tab1 == (tab2_ptr - tab1_ptr) / (sizeof(int) * 2)) ? "PASSED" : "FAILED");
|
||||
printf("Test C99 VLA 3 (ptr add): ");
|
||||
printf("%s\n", &tab1[5][1] == (tab1_ptr + (5 * 2 + 1) * sizeof(int)) ? "PASSED" : "FAILED");
|
||||
printf("Test C99 VLA 4 (ptr access): ");
|
||||
tab1[size1][1] = 42;
|
||||
printf("%s\n", (*((int *) (tab1_ptr + (size1 * 2 + 1) * sizeof(int))) == 42) ? "PASSED" : "FAILED");
|
||||
|
||||
printf("Test C99 VLA 5 (bounds checking (might be disabled)): ");
|
||||
if (bad_ptr = bounds_checking_is_enabled()) {
|
||||
int *t1 = &tab1[size1 * size2 - 1][3];
|
||||
int *t2 = &tab2[9][3];
|
||||
printf("%s ", bad_ptr == t1 ? "PASSED" : "FAILED");
|
||||
printf("%s ", bad_ptr == t2 ? "PASSED" : "FAILED");
|
||||
|
||||
char*c1 = 1 + sizeof(tab1) + (char*)tab1;
|
||||
char*c2 = 1 + sizeof(tab2) + (char*)tab2;
|
||||
printf("%s ", bad_ptr == c1 ? "PASSED" : "FAILED");
|
||||
printf("%s ", bad_ptr == c2 ? "PASSED" : "FAILED");
|
||||
|
||||
int *i1 = tab1[-1];
|
||||
int *i2 = tab2[-1];
|
||||
printf("%s ", bad_ptr == i1 ? "PASSED" : "FAILED");
|
||||
printf("%s ", bad_ptr == i2 ? "PASSED" : "FAILED");
|
||||
|
||||
int *x1 = tab1[size1 * size2 + 1];
|
||||
int *x2 = tab2[10 + 1];
|
||||
printf("%s ", bad_ptr == x1 ? "PASSED" : "FAILED");
|
||||
printf("%s ", bad_ptr == x2 ? "PASSED" : "FAILED");
|
||||
} else {
|
||||
printf("PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED ");
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef __SIZE_TYPE__ uintptr_t;
|
||||
|
||||
void sizeof_test(void)
|
||||
@@ -1969,6 +2187,20 @@ void sizeof_test(void)
|
||||
printf("sizeof(a++) = %d\n", sizeof a++);
|
||||
printf("a=%d\n", a);
|
||||
ptr = NULL;
|
||||
printf("sizeof(**ptr) = %d\n", sizeof (**ptr));
|
||||
|
||||
/* The type of sizeof should be as large as a pointer, actually
|
||||
it should be size_t. */
|
||||
printf("sizeof(sizeof(int) = %d\n", sizeof(sizeof(int)));
|
||||
uintptr_t t = 1;
|
||||
uintptr_t t2;
|
||||
/* Effectively <<32, but defined also on 32bit machines. */
|
||||
t <<= 16;
|
||||
t <<= 16;
|
||||
t++;
|
||||
/* This checks that sizeof really can be used to manipulate
|
||||
uintptr_t objects, without truncation. */
|
||||
t2 = t & -sizeof(uintptr_t);
|
||||
printf ("%lu %lu\n", t, t2);
|
||||
|
||||
/* some alignof tests */
|
||||
@@ -2064,6 +2296,27 @@ __asm__ __volatile__(
|
||||
: "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
|
||||
: "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
static char * strncat2(char * dest,const char * src,size_t count)
|
||||
{
|
||||
int d0, d1, d2, d3;
|
||||
__asm__ __volatile__(
|
||||
"repne scasb\n\t" /* one-line repne prefix + string op */
|
||||
"decl %1\n\t"
|
||||
"movl %8,%3\n"
|
||||
"1:\tdecl %3\n\t"
|
||||
"js 2f\n\t"
|
||||
"lodsb\n\t"
|
||||
"stosb\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b\n"
|
||||
"2:\txorl %2,%2\n\t"
|
||||
"stosb"
|
||||
: "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
|
||||
: "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
|
||||
: "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
static inline void * memcpy1(void * to, const void * from, size_t n)
|
||||
@@ -2082,6 +2335,24 @@ __asm__ __volatile__(
|
||||
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
|
||||
: "memory");
|
||||
return (to);
|
||||
}
|
||||
|
||||
static inline void * memcpy2(void * to, const void * from, size_t n)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
__asm__ __volatile__(
|
||||
"rep movsl\n\t" /* one-line rep prefix + string op */
|
||||
"testb $2,%b4\n\t"
|
||||
"je 1f\n\t"
|
||||
"movsw\n"
|
||||
"1:\ttestb $1,%b4\n\t"
|
||||
"je 2f\n\t"
|
||||
"movsb\n"
|
||||
"2:"
|
||||
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
|
||||
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
|
||||
: "memory");
|
||||
return (to);
|
||||
}
|
||||
|
||||
static __inline__ void sigaddset1(unsigned int *set, int _sig)
|
||||
@@ -2131,6 +2402,10 @@ void asm_test(void)
|
||||
|
||||
memcpy1(buf, "hello", 6);
|
||||
strncat1(buf, " worldXXXXX", 3);
|
||||
printf("%s\n", buf);
|
||||
|
||||
memcpy2(buf, "hello", 6);
|
||||
strncat2(buf, " worldXXXXX", 3);
|
||||
printf("%s\n", buf);
|
||||
|
||||
/* 'A' constraint test */
|
||||
@@ -2191,6 +2466,63 @@ void builtin_test(void)
|
||||
printf("res = %d\n", __builtin_constant_p(1 + 2));
|
||||
printf("res = %d\n", __builtin_constant_p(&constant_p_var));
|
||||
printf("res = %d\n", __builtin_constant_p(constant_p_var));
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
extern int __attribute__((weak)) weak_f1(void);
|
||||
extern int __attribute__((weak)) weak_f2(void);
|
||||
extern int weak_f3(void);
|
||||
extern int __attribute__((weak)) weak_v1;
|
||||
extern int __attribute__((weak)) weak_v2;
|
||||
extern int weak_v3;
|
||||
|
||||
extern int (*weak_fpa)() __attribute__((weak));
|
||||
extern int __attribute__((weak)) (*weak_fpb)();
|
||||
extern __attribute__((weak)) int (*weak_fpc)();
|
||||
|
||||
extern int weak_asm_f1(void) asm("weak_asm_f1x") __attribute((weak));
|
||||
extern int __attribute((weak)) weak_asm_f2(void) asm("weak_asm_f2x") ;
|
||||
extern int __attribute((weak)) weak_asm_f3(void) asm("weak_asm_f3x") __attribute((weak));
|
||||
extern int weak_asm_v1 asm("weak_asm_v1x") __attribute((weak));
|
||||
extern int __attribute((weak)) weak_asm_v2 asm("weak_asm_v2x") ;
|
||||
extern int __attribute((weak)) weak_asm_v3(void) asm("weak_asm_v3x") __attribute((weak));
|
||||
|
||||
static const size_t dummy = 0;
|
||||
extern __typeof(dummy) weak_dummy1 __attribute__((weak, alias("dummy")));
|
||||
extern __typeof(dummy) __attribute__((weak, alias("dummy"))) weak_dummy2;
|
||||
extern __attribute__((weak, alias("dummy"))) __typeof(dummy) weak_dummy3;
|
||||
|
||||
int some_lib_func(void);
|
||||
int dummy_impl_of_slf(void) { return 444; }
|
||||
int some_lib_func(void) __attribute__((weak, alias("dummy_impl_of_slf")));
|
||||
|
||||
int weak_toolate() __attribute__((weak));
|
||||
int weak_toolate() { return 0; }
|
||||
|
||||
void __attribute__((weak)) weak_test(void)
|
||||
{
|
||||
printf("weak_f1=%d\n", weak_f1 ? weak_f1() : 123);
|
||||
printf("weak_f2=%d\n", weak_f2 ? weak_f2() : 123);
|
||||
printf("weak_f3=%d\n", weak_f3 ? weak_f3() : 123);
|
||||
printf("weak_v1=%d\n",&weak_v1 ? weak_v1 : 123);
|
||||
printf("weak_v2=%d\n",&weak_v2 ? weak_v2 : 123);
|
||||
printf("weak_v3=%d\n",&weak_v3 ? weak_v3 : 123);
|
||||
|
||||
printf("weak_fpa=%d\n",&weak_fpa ? weak_fpa() : 123);
|
||||
printf("weak_fpb=%d\n",&weak_fpb ? weak_fpb() : 123);
|
||||
printf("weak_fpc=%d\n",&weak_fpc ? weak_fpc() : 123);
|
||||
|
||||
printf("weak_asm_f1=%d\n", weak_asm_f1 != NULL);
|
||||
printf("weak_asm_f2=%d\n", weak_asm_f2 != NULL);
|
||||
printf("weak_asm_f3=%d\n", weak_asm_f3 != NULL);
|
||||
printf("weak_asm_v1=%d\n",&weak_asm_v1 != NULL);
|
||||
printf("weak_asm_v2=%d\n",&weak_asm_v2 != NULL);
|
||||
printf("weak_asm_v3=%d\n",&weak_asm_v3 != NULL);
|
||||
}
|
||||
|
||||
int __attribute__((weak)) weak_f2() { return 222; }
|
||||
int __attribute__((weak)) weak_f3() { return 333; }
|
||||
int __attribute__((weak)) weak_v2 = 222;
|
||||
int __attribute__((weak)) weak_v3 = 333;
|
||||
#endif
|
||||
|
||||
@@ -2200,3 +2532,182 @@ void const_warn_test(void)
|
||||
|
||||
void const_warn_test(void)
|
||||
{
|
||||
const_func(1);
|
||||
}
|
||||
|
||||
struct condstruct {
|
||||
int i;
|
||||
};
|
||||
|
||||
int getme (struct condstruct *s, int i)
|
||||
{
|
||||
int i1 = (i == 0 ? 0 : s)->i;
|
||||
int i2 = (i == 0 ? s : 0)->i;
|
||||
int i3 = (i == 0 ? (void*)0 : s)->i;
|
||||
int i4 = (i == 0 ? s : (void*)0)->i;
|
||||
return i1 + i2 + i3 + i4;
|
||||
}
|
||||
|
||||
struct global_data
|
||||
{
|
||||
int a[40];
|
||||
int *b[40];
|
||||
};
|
||||
|
||||
struct global_data global_data;
|
||||
|
||||
int global_data_getstuff (int *, int);
|
||||
|
||||
void global_data_callit (int i)
|
||||
{
|
||||
*global_data.b[i] = global_data_getstuff (global_data.b[i], 1);
|
||||
}
|
||||
|
||||
int global_data_getstuff (int *p, int i)
|
||||
{
|
||||
return *p + i;
|
||||
}
|
||||
|
||||
void global_data_test (void)
|
||||
{
|
||||
global_data.a[0] = 42;
|
||||
global_data.b[0] = &global_data.a[0];
|
||||
global_data_callit (0);
|
||||
printf ("%d\n", global_data.a[0]);
|
||||
}
|
||||
|
||||
struct cmpcmpS
|
||||
{
|
||||
unsigned char fill : 3;
|
||||
unsigned char b1 : 1;
|
||||
unsigned char b2 : 1;
|
||||
unsigned char fill2 : 3;
|
||||
};
|
||||
|
||||
int glob1, glob2, glob3;
|
||||
|
||||
void compare_comparisons (struct cmpcmpS *s)
|
||||
{
|
||||
if (s->b1 != (glob1 == glob2)
|
||||
|| (s->b2 != (glob1 == glob3)))
|
||||
printf ("comparing comparisons broken\n");
|
||||
}
|
||||
|
||||
void cmp_comparison_test(void)
|
||||
{
|
||||
struct cmpcmpS s;
|
||||
s.b1 = 1;
|
||||
glob1 = 42; glob2 = 42;
|
||||
s.b2 = 0;
|
||||
glob3 = 43;
|
||||
compare_comparisons (&s);
|
||||
}
|
||||
|
||||
int fcompare (double a, double b, int code)
|
||||
{
|
||||
switch (code) {
|
||||
case 0: return a == b;
|
||||
case 1: return a != b;
|
||||
case 2: return a < b;
|
||||
case 3: return a >= b;
|
||||
case 4: return a > b;
|
||||
case 5: return a <= b;
|
||||
}
|
||||
}
|
||||
|
||||
void math_cmp_test(void)
|
||||
{
|
||||
double nan = 0.0/0.0;
|
||||
double one = 1.0;
|
||||
double two = 2.0;
|
||||
int comp = 0;
|
||||
#define bug(a,b,op,iop,part) printf("Test broken: %s %s %s %s %d\n", #a, #b, #op, #iop, part)
|
||||
|
||||
/* This asserts that "a op b" is _not_ true, but "a iop b" is true.
|
||||
And it does this in various ways so that all code generation paths
|
||||
are checked (generating inverted tests, or non-inverted tests, or
|
||||
producing a 0/1 value without jumps (that's done in the fcompare
|
||||
function). */
|
||||
#define FCMP(a,b,op,iop,code) \
|
||||
if (fcompare (a,b,code)) \
|
||||
bug (a,b,op,iop,1); \
|
||||
if (a op b) \
|
||||
bug (a,b,op,iop,2); \
|
||||
if (a iop b) \
|
||||
; \
|
||||
else \
|
||||
bug (a,b,op,iop,3); \
|
||||
if ((a op b) || comp) \
|
||||
bug (a,b,op,iop,4); \
|
||||
if ((a iop b) || comp) \
|
||||
; \
|
||||
else \
|
||||
bug (a,b,op,iop,5);
|
||||
|
||||
/* Equality tests. */
|
||||
FCMP(nan, nan, ==, !=, 0);
|
||||
FCMP(one, two, ==, !=, 0);
|
||||
FCMP(one, one, !=, ==, 1);
|
||||
/* Non-equality is a bit special. */
|
||||
if (!fcompare (nan, nan, 1))
|
||||
bug (nan, nan, !=, ==, 6);
|
||||
|
||||
/* Relational tests on numbers. */
|
||||
FCMP(two, one, <, >=, 2);
|
||||
FCMP(one, two, >=, <, 3);
|
||||
FCMP(one, two, >, <=, 4);
|
||||
FCMP(two, one, <=, >, 5);
|
||||
|
||||
/* Relational tests on NaNs. Note that the inverse op here is
|
||||
always !=, there's no operator in C that is equivalent to !(a < b),
|
||||
when NaNs are involved, same for the other relational ops. */
|
||||
FCMP(nan, nan, <, !=, 2);
|
||||
FCMP(nan, nan, >=, !=, 3);
|
||||
FCMP(nan, nan, >, !=, 4);
|
||||
FCMP(nan, nan, <=, !=, 5);
|
||||
}
|
||||
|
||||
double get100 () { return 100.0; }
|
||||
|
||||
void callsave_test(void)
|
||||
{
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
int i, s; double *d; double t;
|
||||
s = sizeof (double);
|
||||
printf ("callsavetest: %d\n", s);
|
||||
d = alloca (sizeof(double));
|
||||
d[0] = 10.0;
|
||||
/* x86-64 had a bug were the next call to get100 would evict
|
||||
the lvalue &d[0] as VT_LLOCAL, and the reload would be done
|
||||
in int type, not pointer type. When alloca returns a pointer
|
||||
with the high 32 bit set (which is likely on x86-64) the access
|
||||
generates a segfault. */
|
||||
i = d[0] > get100 ();
|
||||
printf ("%d\n", i);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void bfa3(ptrdiff_t str_offset)
|
||||
{
|
||||
printf("bfa3: %s\n", (char *)__builtin_frame_address(3) + str_offset);
|
||||
}
|
||||
void bfa2(ptrdiff_t str_offset)
|
||||
{
|
||||
printf("bfa2: %s\n", (char *)__builtin_frame_address(2) + str_offset);
|
||||
bfa3(str_offset);
|
||||
}
|
||||
void bfa1(ptrdiff_t str_offset)
|
||||
{
|
||||
printf("bfa1: %s\n", (char *)__builtin_frame_address(1) + str_offset);
|
||||
#if defined(__arm__) && !defined(__GNUC__)
|
||||
bfa2(str_offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
void builtin_frame_address_test(void)
|
||||
{
|
||||
char str[] = "__builtin_frame_address";
|
||||
char *fp0 = __builtin_frame_address(0);
|
||||
|
||||
printf("str: %s\n", str);
|
||||
|
||||
18
tests/tests2/00_assignment.c
Normal file
18
tests/tests2/00_assignment.c
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int a;
|
||||
a = 42;
|
||||
printf("%d\n", a);
|
||||
|
||||
int b = 64;
|
||||
printf("%d\n", b);
|
||||
|
||||
int c = 12, d = 34;
|
||||
printf("%d, %d\n", c, d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: set expandtab ts=4 sw=3 sts=3 tw=80 :
|
||||
3
tests/tests2/00_assignment.expect
Normal file
3
tests/tests2/00_assignment.expect
Normal file
@@ -0,0 +1,3 @@
|
||||
42
|
||||
64
|
||||
12, 34
|
||||
14
tests/tests2/01_comment.c
Normal file
14
tests/tests2/01_comment.c
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("Hello\n");
|
||||
printf("Hello\n"); /* this is a comment */ printf("Hello\n");
|
||||
printf("Hello\n");
|
||||
// this is also a comment sayhello();
|
||||
printf("Hello\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: set expandtab ts=4 sw=3 sts=3 tw=80 :
|
||||
5
tests/tests2/01_comment.expect
Normal file
5
tests/tests2/01_comment.expect
Normal file
@@ -0,0 +1,5 @@
|
||||
Hello
|
||||
Hello
|
||||
Hello
|
||||
Hello
|
||||
Hello
|
||||
18
tests/tests2/02_printf.c
Normal file
18
tests/tests2/02_printf.c
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("Hello world\n");
|
||||
|
||||
int Count;
|
||||
for (Count = -5; Count <= 5; Count++)
|
||||
printf("Count = %d\n", Count);
|
||||
|
||||
printf("String 'hello', 'there' is '%s', '%s'\n", "hello", "there");
|
||||
printf("Character 'A' is '%c'\n", 65);
|
||||
printf("Character 'a' is '%c'\n", 'a');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: set expandtab ts=4 sw=3 sts=3 tw=80 :
|
||||
15
tests/tests2/02_printf.expect
Normal file
15
tests/tests2/02_printf.expect
Normal file
@@ -0,0 +1,15 @@
|
||||
Hello world
|
||||
Count = -5
|
||||
Count = -4
|
||||
Count = -3
|
||||
Count = -2
|
||||
Count = -1
|
||||
Count = 0
|
||||
Count = 1
|
||||
Count = 2
|
||||
Count = 3
|
||||
Count = 4
|
||||
Count = 5
|
||||
String 'hello', 'there' is 'hello', 'there'
|
||||
Character 'A' is 'A'
|
||||
Character 'a' is 'a'
|
||||
31
tests/tests2/03_struct.c
Normal file
31
tests/tests2/03_struct.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <stdio.h>
|
||||
|
||||
struct fred
|
||||
{
|
||||
int boris;
|
||||
int natasha;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
struct fred bloggs;
|
||||
|
||||
bloggs.boris = 12;
|
||||
bloggs.natasha = 34;
|
||||
|
||||
printf("%d\n", bloggs.boris);
|
||||
printf("%d\n", bloggs.natasha);
|
||||
|
||||
struct fred jones[2];
|
||||
jones[0].boris = 12;
|
||||
jones[0].natasha = 34;
|
||||
jones[1].boris = 56;
|
||||
jones[1].natasha = 78;
|
||||
|
||||
printf("%d\n", jones[0].boris);
|
||||
printf("%d\n", jones[0].natasha);
|
||||
printf("%d\n", jones[1].boris);
|
||||
printf("%d\n", jones[1].natasha);
|
||||
|
||||
return 0;
|
||||
}
|
||||
6
tests/tests2/03_struct.expect
Normal file
6
tests/tests2/03_struct.expect
Normal file
@@ -0,0 +1,6 @@
|
||||
12
|
||||
34
|
||||
12
|
||||
34
|
||||
56
|
||||
78
|
||||
15
tests/tests2/04_for.c
Normal file
15
tests/tests2/04_for.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int Count;
|
||||
|
||||
for (Count = 1; Count <= 10; Count++)
|
||||
{
|
||||
printf("%d\n", Count);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: set expandtab ts=4 sw=3 sts=3 tw=80 :
|
||||
10
tests/tests2/04_for.expect
Normal file
10
tests/tests2/04_for.expect
Normal file
@@ -0,0 +1,10 @@
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
21
tests/tests2/05_array.c
Normal file
21
tests/tests2/05_array.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int Count;
|
||||
int Array[10];
|
||||
|
||||
for (Count = 1; Count <= 10; Count++)
|
||||
{
|
||||
Array[Count-1] = Count * Count;
|
||||
}
|
||||
|
||||
for (Count = 0; Count < 10; Count++)
|
||||
{
|
||||
printf("%d\n", Array[Count]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: set expandtab ts=4 sw=3 sts=3 tw=80 :
|
||||
10
tests/tests2/05_array.expect
Normal file
10
tests/tests2/05_array.expect
Normal file
@@ -0,0 +1,10 @@
|
||||
1
|
||||
4
|
||||
9
|
||||
16
|
||||
25
|
||||
36
|
||||
49
|
||||
64
|
||||
81
|
||||
100
|
||||
29
tests/tests2/06_case.c
Normal file
29
tests/tests2/06_case.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int Count;
|
||||
|
||||
for (Count = 0; Count < 4; Count++)
|
||||
{
|
||||
printf("%d\n", Count);
|
||||
switch (Count)
|
||||
{
|
||||
case 1:
|
||||
printf("%d\n", 1);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
printf("%d\n", 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%d\n", 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: set expandtab ts=4 sw=3 sts=3 tw=80 :
|
||||
8
tests/tests2/06_case.expect
Normal file
8
tests/tests2/06_case.expect
Normal file
@@ -0,0 +1,8 @@
|
||||
0
|
||||
0
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
3
|
||||
0
|
||||
30
tests/tests2/07_function.c
Normal file
30
tests/tests2/07_function.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int myfunc(int x)
|
||||
{
|
||||
return x * x;
|
||||
}
|
||||
|
||||
void vfunc(int a)
|
||||
{
|
||||
printf("a=%d\n", a);
|
||||
}
|
||||
|
||||
void qfunc()
|
||||
{
|
||||
printf("qfunc()\n");
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("%d\n", myfunc(3));
|
||||
printf("%d\n", myfunc(4));
|
||||
|
||||
vfunc(1234);
|
||||
|
||||
qfunc();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: set expandtab ts=4 sw=3 sts=3 tw=80 :
|
||||
4
tests/tests2/07_function.expect
Normal file
4
tests/tests2/07_function.expect
Normal file
@@ -0,0 +1,4 @@
|
||||
9
|
||||
16
|
||||
a=1234
|
||||
qfunc()
|
||||
24
tests/tests2/08_while.c
Normal file
24
tests/tests2/08_while.c
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int a;
|
||||
int p;
|
||||
int t;
|
||||
|
||||
a = 1;
|
||||
p = 0;
|
||||
t = 0;
|
||||
|
||||
while (a < 100)
|
||||
{
|
||||
printf("%d\n", a);
|
||||
t = a;
|
||||
a = t + p;
|
||||
p = t;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: set expandtab ts=4 sw=3 sts=3 tw=80 :
|
||||
11
tests/tests2/08_while.expect
Normal file
11
tests/tests2/08_while.expect
Normal file
@@ -0,0 +1,11 @@
|
||||
1
|
||||
1
|
||||
2
|
||||
3
|
||||
5
|
||||
8
|
||||
13
|
||||
21
|
||||
34
|
||||
55
|
||||
89
|
||||
24
tests/tests2/09_do_while.c
Normal file
24
tests/tests2/09_do_while.c
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int a;
|
||||
int p;
|
||||
int t;
|
||||
|
||||
a = 1;
|
||||
p = 0;
|
||||
t = 0;
|
||||
|
||||
do
|
||||
{
|
||||
printf("%d\n", a);
|
||||
t = a;
|
||||
a = t + p;
|
||||
p = t;
|
||||
} while (a < 100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: set expandtab ts=4 sw=3 sts=3 tw=80 :
|
||||
11
tests/tests2/09_do_while.expect
Normal file
11
tests/tests2/09_do_while.expect
Normal file
@@ -0,0 +1,11 @@
|
||||
1
|
||||
1
|
||||
2
|
||||
3
|
||||
5
|
||||
8
|
||||
13
|
||||
21
|
||||
34
|
||||
55
|
||||
89
|
||||
40
tests/tests2/10_pointer.c
Normal file
40
tests/tests2/10_pointer.c
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <stdio.h>
|
||||
|
||||
struct ziggy
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
} bolshevic;
|
||||
|
||||
int main()
|
||||
{
|
||||
int a;
|
||||
int *b;
|
||||
int c;
|
||||
|
||||
a = 42;
|
||||
b = &a;
|
||||
printf("a = %d\n", *b);
|
||||
|
||||
bolshevic.a = 12;
|
||||
bolshevic.b = 34;
|
||||
bolshevic.c = 56;
|
||||
|
||||
printf("bolshevic.a = %d\n", bolshevic.a);
|
||||
printf("bolshevic.b = %d\n", bolshevic.b);
|
||||
printf("bolshevic.c = %d\n", bolshevic.c);
|
||||
|
||||
struct ziggy *tsar = &bolshevic;
|
||||
|
||||
printf("tsar->a = %d\n", tsar->a);
|
||||
printf("tsar->b = %d\n", tsar->b);
|
||||
printf("tsar->c = %d\n", tsar->c);
|
||||
|
||||
b = &(bolshevic.b);
|
||||
printf("bolshevic.b = %d\n", *b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: set expandtab ts=4 sw=3 sts=3 tw=80 :
|
||||
8
tests/tests2/10_pointer.expect
Normal file
8
tests/tests2/10_pointer.expect
Normal file
@@ -0,0 +1,8 @@
|
||||
a = 42
|
||||
bolshevic.a = 12
|
||||
bolshevic.b = 34
|
||||
bolshevic.c = 56
|
||||
tsar->a = 12
|
||||
tsar->b = 34
|
||||
tsar->c = 56
|
||||
bolshevic.b = 34
|
||||
40
tests/tests2/11_precedence.c
Normal file
40
tests/tests2/11_precedence.c
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
int d;
|
||||
int e;
|
||||
int f;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
a = 12;
|
||||
b = 34;
|
||||
c = 56;
|
||||
d = 78;
|
||||
e = 0;
|
||||
f = 1;
|
||||
|
||||
printf("%d\n", c + d);
|
||||
printf("%d\n", (y = c + d));
|
||||
printf("%d\n", e || e && f);
|
||||
printf("%d\n", e || f && f);
|
||||
printf("%d\n", e && e || f);
|
||||
printf("%d\n", e && f || f);
|
||||
printf("%d\n", a && f | f);
|
||||
printf("%d\n", a | b ^ c & d);
|
||||
printf("%d, %d\n", a == a, a == b);
|
||||
printf("%d, %d\n", a != a, a != b);
|
||||
printf("%d\n", a != b && c != d);
|
||||
printf("%d\n", a + b * c / f);
|
||||
printf("%d\n", a + b * c / f);
|
||||
printf("%d\n", (4 << 4));
|
||||
printf("%d\n", (64 >> 4));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: set expandtab ts=4 sw=3 sts=3 tw=80 :
|
||||
15
tests/tests2/11_precedence.expect
Normal file
15
tests/tests2/11_precedence.expect
Normal file
@@ -0,0 +1,15 @@
|
||||
134
|
||||
134
|
||||
0
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
46
|
||||
1, 0
|
||||
0, 1
|
||||
1
|
||||
1916
|
||||
1916
|
||||
64
|
||||
4
|
||||
14
tests/tests2/12_hashdefine.c
Normal file
14
tests/tests2/12_hashdefine.c
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#define FRED 12
|
||||
#define BLOGGS(x) (12*(x))
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("%d\n", FRED);
|
||||
printf("%d, %d, %d\n", BLOGGS(1), BLOGGS(2), BLOGGS(3));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: set expandtab ts=4 sw=3 sts=3 tw=80 :
|
||||
2
tests/tests2/12_hashdefine.expect
Normal file
2
tests/tests2/12_hashdefine.expect
Normal file
@@ -0,0 +1,2 @@
|
||||
12
|
||||
12, 24, 36
|
||||
20
tests/tests2/13_integer_literals.c
Normal file
20
tests/tests2/13_integer_literals.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int a = 24680;
|
||||
int b = 01234567;
|
||||
int c = 0x2468ac;
|
||||
int d = 0x2468AC;
|
||||
int e = 0b010101010101;
|
||||
|
||||
printf("%d\n", a);
|
||||
printf("%d\n", b);
|
||||
printf("%d\n", c);
|
||||
printf("%d\n", d);
|
||||
printf("%d\n", e);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: set expandtab ts=4 sw=3 sts=3 tw=80 :
|
||||
5
tests/tests2/13_integer_literals.expect
Normal file
5
tests/tests2/13_integer_literals.expect
Normal file
@@ -0,0 +1,5 @@
|
||||
24680
|
||||
342391
|
||||
2386092
|
||||
2386092
|
||||
1365
|
||||
21
tests/tests2/14_if.c
Normal file
21
tests/tests2/14_if.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int a = 1;
|
||||
|
||||
if (a)
|
||||
printf("a is true\n");
|
||||
else
|
||||
printf("a is false\n");
|
||||
|
||||
int b = 0;
|
||||
if (b)
|
||||
printf("b is true\n");
|
||||
else
|
||||
printf("b is false\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: set expandtab ts=4 sw=3 sts=3 tw=80 :
|
||||
2
tests/tests2/14_if.expect
Normal file
2
tests/tests2/14_if.expect
Normal file
@@ -0,0 +1,2 @@
|
||||
a is true
|
||||
b is false
|
||||
21
tests/tests2/15_recursion.c
Normal file
21
tests/tests2/15_recursion.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int factorial(int i)
|
||||
{
|
||||
if (i < 2)
|
||||
return i;
|
||||
else
|
||||
return i * factorial(i - 1);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int Count;
|
||||
|
||||
for (Count = 1; Count <= 10; Count++)
|
||||
printf("%d\n", factorial(Count));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
|
||||
10
tests/tests2/15_recursion.expect
Normal file
10
tests/tests2/15_recursion.expect
Normal file
@@ -0,0 +1,10 @@
|
||||
1
|
||||
2
|
||||
6
|
||||
24
|
||||
120
|
||||
720
|
||||
5040
|
||||
40320
|
||||
362880
|
||||
3628800
|
||||
21
tests/tests2/16_nesting.c
Normal file
21
tests/tests2/16_nesting.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int x, y, z;
|
||||
|
||||
for (x = 0; x < 2; x++)
|
||||
{
|
||||
for (y = 0; y < 3; y++)
|
||||
{
|
||||
for (z = 0; z < 3; z++)
|
||||
{
|
||||
printf("%d %d %d\n", x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
|
||||
18
tests/tests2/16_nesting.expect
Normal file
18
tests/tests2/16_nesting.expect
Normal file
@@ -0,0 +1,18 @@
|
||||
0 0 0
|
||||
0 0 1
|
||||
0 0 2
|
||||
0 1 0
|
||||
0 1 1
|
||||
0 1 2
|
||||
0 2 0
|
||||
0 2 1
|
||||
0 2 2
|
||||
1 0 0
|
||||
1 0 1
|
||||
1 0 2
|
||||
1 1 0
|
||||
1 1 1
|
||||
1 1 2
|
||||
1 2 0
|
||||
1 2 1
|
||||
1 2 2
|
||||
29
tests/tests2/17_enum.c
Normal file
29
tests/tests2/17_enum.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <stdio.h>
|
||||
|
||||
enum fred
|
||||
{
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
e = 54,
|
||||
f = 73,
|
||||
g,
|
||||
h
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
enum fred frod;
|
||||
|
||||
printf("%d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h);
|
||||
/* printf("%d\n", frod); */
|
||||
frod = 12;
|
||||
printf("%d\n", frod);
|
||||
frod = e;
|
||||
printf("%d\n", frod);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
|
||||
3
tests/tests2/17_enum.expect
Normal file
3
tests/tests2/17_enum.expect
Normal file
@@ -0,0 +1,3 @@
|
||||
0 1 2 3 54 73 74 75
|
||||
12
|
||||
54
|
||||
12
tests/tests2/18_include.c
Normal file
12
tests/tests2/18_include.c
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("including\n");
|
||||
#include "18_include.h"
|
||||
printf("done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
|
||||
3
tests/tests2/18_include.expect
Normal file
3
tests/tests2/18_include.expect
Normal file
@@ -0,0 +1,3 @@
|
||||
including
|
||||
included
|
||||
done
|
||||
1
tests/tests2/18_include.h
Normal file
1
tests/tests2/18_include.h
Normal file
@@ -0,0 +1 @@
|
||||
printf("included\n");
|
||||
28
tests/tests2/19_pointer_arithmetic.c
Normal file
28
tests/tests2/19_pointer_arithmetic.c
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int a;
|
||||
int *b;
|
||||
int *c;
|
||||
|
||||
a = 42;
|
||||
b = &a;
|
||||
c = NULL;
|
||||
|
||||
printf("%d\n", *b);
|
||||
|
||||
if (b == NULL)
|
||||
printf("b is NULL\n");
|
||||
else
|
||||
printf("b is not NULL\n");
|
||||
|
||||
if (c == NULL)
|
||||
printf("c is NULL\n");
|
||||
else
|
||||
printf("c is not NULL\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
|
||||
3
tests/tests2/19_pointer_arithmetic.expect
Normal file
3
tests/tests2/19_pointer_arithmetic.expect
Normal file
@@ -0,0 +1,3 @@
|
||||
42
|
||||
b is not NULL
|
||||
c is NULL
|
||||
24
tests/tests2/20_pointer_comparison.c
Normal file
24
tests/tests2/20_pointer_comparison.c
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
int *d;
|
||||
int *e;
|
||||
d = &a;
|
||||
e = &b;
|
||||
a = 12;
|
||||
b = 34;
|
||||
printf("%d\n", *d);
|
||||
printf("%d\n", *e);
|
||||
printf("%d\n", d == e);
|
||||
printf("%d\n", d != e);
|
||||
d = e;
|
||||
printf("%d\n", d == e);
|
||||
printf("%d\n", d != e);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
|
||||
6
tests/tests2/20_pointer_comparison.expect
Normal file
6
tests/tests2/20_pointer_comparison.expect
Normal file
@@ -0,0 +1,6 @@
|
||||
12
|
||||
34
|
||||
0
|
||||
1
|
||||
1
|
||||
0
|
||||
33
tests/tests2/21_char_array.c
Normal file
33
tests/tests2/21_char_array.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int x = 'a';
|
||||
char y = x;
|
||||
|
||||
char *a = "hello";
|
||||
|
||||
printf("%s\n", a);
|
||||
|
||||
int c;
|
||||
c = *a;
|
||||
|
||||
char *b;
|
||||
for (b = a; *b != 0; b++)
|
||||
printf("%c: %d\n", *b, *b);
|
||||
|
||||
char destarray[10];
|
||||
char *dest = &destarray[0];
|
||||
char *src = a;
|
||||
|
||||
while (*src != 0)
|
||||
*dest++ = *src++;
|
||||
|
||||
*dest = 0;
|
||||
|
||||
printf("copied string is %s\n", destarray);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
|
||||
7
tests/tests2/21_char_array.expect
Normal file
7
tests/tests2/21_char_array.expect
Normal file
@@ -0,0 +1,7 @@
|
||||
hello
|
||||
h: 104
|
||||
e: 101
|
||||
l: 108
|
||||
l: 108
|
||||
o: 111
|
||||
copied string is hello
|
||||
50
tests/tests2/22_floating_point.c
Normal file
50
tests/tests2/22_floating_point.c
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
// variables
|
||||
float a = 12.34 + 56.78;
|
||||
printf("%f\n", a);
|
||||
|
||||
// infix operators
|
||||
printf("%f\n", 12.34 + 56.78);
|
||||
printf("%f\n", 12.34 - 56.78);
|
||||
printf("%f\n", 12.34 * 56.78);
|
||||
printf("%f\n", 12.34 / 56.78);
|
||||
|
||||
// comparison operators
|
||||
printf("%d %d %d %d %d %d\n", 12.34 < 56.78, 12.34 <= 56.78, 12.34 == 56.78, 12.34 >= 56.78, 12.34 > 56.78, 12.34 != 56.78);
|
||||
printf("%d %d %d %d %d %d\n", 12.34 < 12.34, 12.34 <= 12.34, 12.34 == 12.34, 12.34 >= 12.34, 12.34 > 12.34, 12.34 != 12.34);
|
||||
printf("%d %d %d %d %d %d\n", 56.78 < 12.34, 56.78 <= 12.34, 56.78 == 12.34, 56.78 >= 12.34, 56.78 > 12.34, 56.78 != 12.34);
|
||||
|
||||
// assignment operators
|
||||
a = 12.34;
|
||||
a += 56.78;
|
||||
printf("%f\n", a);
|
||||
|
||||
a = 12.34;
|
||||
a -= 56.78;
|
||||
printf("%f\n", a);
|
||||
|
||||
a = 12.34;
|
||||
a *= 56.78;
|
||||
printf("%f\n", a);
|
||||
|
||||
a = 12.34;
|
||||
a /= 56.78;
|
||||
printf("%f\n", a);
|
||||
|
||||
// prefix operators
|
||||
printf("%f\n", +12.34);
|
||||
printf("%f\n", -12.34);
|
||||
|
||||
// type coercion
|
||||
a = 2;
|
||||
printf("%f\n", a);
|
||||
printf("%f\n", sin(2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
|
||||
16
tests/tests2/22_floating_point.expect
Normal file
16
tests/tests2/22_floating_point.expect
Normal file
@@ -0,0 +1,16 @@
|
||||
69.120003
|
||||
69.120000
|
||||
-44.440000
|
||||
700.665200
|
||||
0.217330
|
||||
1 1 0 0 0 1
|
||||
0 1 1 1 0 0
|
||||
0 0 0 1 1 1
|
||||
69.120003
|
||||
-44.439999
|
||||
700.665222
|
||||
0.217330
|
||||
12.340000
|
||||
-12.340000
|
||||
2.000000
|
||||
0.909297
|
||||
54
tests/tests2/23_type_coercion.c
Normal file
54
tests/tests2/23_type_coercion.c
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void charfunc(char a)
|
||||
{
|
||||
printf("char: %c\n", a);
|
||||
}
|
||||
|
||||
void intfunc(int a)
|
||||
{
|
||||
printf("int: %d\n", a);
|
||||
}
|
||||
|
||||
void floatfunc(float a)
|
||||
{
|
||||
printf("float: %f\n", a);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
charfunc('a');
|
||||
charfunc(98);
|
||||
charfunc(99.0);
|
||||
|
||||
intfunc('a');
|
||||
intfunc(98);
|
||||
intfunc(99.0);
|
||||
|
||||
floatfunc('a');
|
||||
floatfunc(98);
|
||||
floatfunc(99.0);
|
||||
|
||||
/* printf("%c %d %f\n", 'a', 'b', 'c'); */
|
||||
/* printf("%c %d %f\n", 97, 98, 99); */
|
||||
/* printf("%c %d %f\n", 97.0, 98.0, 99.0); */
|
||||
|
||||
char b = 97;
|
||||
char c = 97.0;
|
||||
|
||||
printf("%d %d\n", b, c);
|
||||
|
||||
int d = 'a';
|
||||
int e = 97.0;
|
||||
|
||||
printf("%d %d\n", d, e);
|
||||
|
||||
float f = 'a';
|
||||
float g = 97;
|
||||
|
||||
printf("%f %f\n", f, g);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
|
||||
12
tests/tests2/23_type_coercion.expect
Normal file
12
tests/tests2/23_type_coercion.expect
Normal file
@@ -0,0 +1,12 @@
|
||||
char: a
|
||||
char: b
|
||||
char: c
|
||||
int: 97
|
||||
int: 98
|
||||
int: 99
|
||||
float: 97.000000
|
||||
float: 98.000000
|
||||
float: 99.000000
|
||||
97 97
|
||||
97 97
|
||||
97.000000 97.000000
|
||||
28
tests/tests2/24_math_library.c
Normal file
28
tests/tests2/24_math_library.c
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("%f\n", sin(0.12));
|
||||
printf("%f\n", cos(0.12));
|
||||
printf("%f\n", tan(0.12));
|
||||
printf("%f\n", asin(0.12));
|
||||
printf("%f\n", acos(0.12));
|
||||
printf("%f\n", atan(0.12));
|
||||
printf("%f\n", sinh(0.12));
|
||||
printf("%f\n", cosh(0.12));
|
||||
printf("%f\n", tanh(0.12));
|
||||
printf("%f\n", exp(0.12));
|
||||
printf("%f\n", fabs(-0.12));
|
||||
printf("%f\n", log(0.12));
|
||||
printf("%f\n", log10(0.12));
|
||||
printf("%f\n", pow(0.12, 0.12));
|
||||
printf("%f\n", sqrt(0.12));
|
||||
printf("%f\n", round(12.34));
|
||||
printf("%f\n", ceil(12.34));
|
||||
printf("%f\n", floor(12.34));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
|
||||
18
tests/tests2/24_math_library.expect
Normal file
18
tests/tests2/24_math_library.expect
Normal file
@@ -0,0 +1,18 @@
|
||||
0.119712
|
||||
0.992809
|
||||
0.120579
|
||||
0.120290
|
||||
1.450506
|
||||
0.119429
|
||||
0.120288
|
||||
1.007209
|
||||
0.119427
|
||||
1.127497
|
||||
0.120000
|
||||
-2.120264
|
||||
-0.920819
|
||||
0.775357
|
||||
0.346410
|
||||
12.000000
|
||||
13.000000
|
||||
12.000000
|
||||
83
tests/tests2/25_quicksort.c
Normal file
83
tests/tests2/25_quicksort.c
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int array[16];
|
||||
|
||||
//Swap integer values by array indexes
|
||||
void swap(int a, int b)
|
||||
{
|
||||
int tmp = array[a];
|
||||
array[a] = array[b];
|
||||
array[b] = tmp;
|
||||
}
|
||||
|
||||
//Partition the array into two halves and return the
|
||||
//index about which the array is partitioned
|
||||
int partition(int left, int right)
|
||||
{
|
||||
int pivotIndex = left;
|
||||
int pivotValue = array[pivotIndex];
|
||||
int index = left;
|
||||
int i;
|
||||
|
||||
swap(pivotIndex, right);
|
||||
for(i = left; i < right; i++)
|
||||
{
|
||||
if(array[i] < pivotValue)
|
||||
{
|
||||
swap(i, index);
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
swap(right, index);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
//Quicksort the array
|
||||
void quicksort(int left, int right)
|
||||
{
|
||||
if(left >= right)
|
||||
return;
|
||||
|
||||
int index = partition(left, right);
|
||||
quicksort(left, index - 1);
|
||||
quicksort(index + 1, right);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
|
||||
array[0] = 62;
|
||||
array[1] = 83;
|
||||
array[2] = 4;
|
||||
array[3] = 89;
|
||||
array[4] = 36;
|
||||
array[5] = 21;
|
||||
array[6] = 74;
|
||||
array[7] = 37;
|
||||
array[8] = 65;
|
||||
array[9] = 33;
|
||||
array[10] = 96;
|
||||
array[11] = 38;
|
||||
array[12] = 53;
|
||||
array[13] = 16;
|
||||
array[14] = 74;
|
||||
array[15] = 55;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
printf("%d ", array[i]);
|
||||
|
||||
printf("\n");
|
||||
|
||||
quicksort(0, 15);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
printf("%d ", array[i]);
|
||||
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
|
||||
2
tests/tests2/25_quicksort.expect
Normal file
2
tests/tests2/25_quicksort.expect
Normal file
@@ -0,0 +1,2 @@
|
||||
62 83 4 89 36 21 74 37 65 33 96 38 53 16 74 55
|
||||
4 16 21 33 36 37 38 53 55 62 65 74 74 83 89 96
|
||||
17
tests/tests2/26_character_constants.c
Normal file
17
tests/tests2/26_character_constants.c
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("%d\n", '\1');
|
||||
printf("%d\n", '\10');
|
||||
printf("%d\n", '\100');
|
||||
printf("%d\n", '\x01');
|
||||
printf("%d\n", '\x0e');
|
||||
printf("%d\n", '\x10');
|
||||
printf("%d\n", '\x40');
|
||||
printf("test \x40\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user