mirror of
https://github.com/mirror/tinycc.git
synced 2026-08-24 11:33:28 +08:00
Compare commits
877 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 | ||
|
|
110a4edc15 | ||
|
|
68310299b6 | ||
|
|
bf8d8f5f3e | ||
|
|
aed6a7cb60 | ||
|
|
530b77e365 | ||
|
|
ca4b4a52ad | ||
|
|
03c787d6ce | ||
|
|
40f5ce002e | ||
|
|
67aebdd5b7 | ||
|
|
0a35f9d66e | ||
|
|
f9181416f6 | ||
|
|
5c6509578e | ||
|
|
b8f6e1ae30 | ||
|
|
92204e8818 | ||
|
|
9dc9cbf319 | ||
|
|
0d1ed74102 | ||
|
|
805990b94e | ||
|
|
ae37bd5abc | ||
|
|
a93bcdffae | ||
|
|
15626621fb | ||
|
|
e9e89ad699 | ||
|
|
859da934e0 | ||
|
|
48ae0c0468 | ||
|
|
5829791ffa | ||
|
|
ea5e81bd6a | ||
|
|
e8a52a8249 | ||
|
|
eca1fbaf92 | ||
|
|
b56f956247 | ||
|
|
d165e87340 | ||
|
|
73ba078d2f | ||
|
|
d36fea34e3 | ||
|
|
dd5630ff95 | ||
|
|
0f0ed4a8bf | ||
|
|
90697c4c56 | ||
|
|
d62301b050 | ||
|
|
9a7173bf69 | ||
|
|
e6ba81b012 | ||
|
|
b1697be691 | ||
|
|
795f67428e | ||
|
|
9a8b2912ed | ||
|
|
742cf05875 | ||
|
|
85d016b507 | ||
|
|
39a4b859d4 | ||
|
|
51a7f163ad | ||
|
|
83fd36333a | ||
|
|
be43c8e0ed | ||
|
|
a9c78d04f2 | ||
|
|
b879ffa193 | ||
|
|
de3f0a46fe | ||
|
|
2e9b57b6d0 | ||
|
|
9fe28b610e | ||
|
|
0e239e2ba5 | ||
|
|
fcf2e5981f | ||
|
|
830b7533c9 | ||
|
|
6c10429aa5 | ||
|
|
29c8e1545a | ||
|
|
c80f81c199 | ||
|
|
5818945ef6 | ||
|
|
0e015988cc | ||
|
|
97072b3cd7 | ||
|
|
754b0beb7d | ||
|
|
e6db5f5fb6 | ||
|
|
06fa15fb99 | ||
|
|
ebb874e216 | ||
|
|
6512d9e2ea | ||
|
|
af6cbc48d1 | ||
|
|
040ef000e4 | ||
|
|
fe8f230ab6 | ||
|
|
b8a32d8d40 | ||
|
|
7db1e69df2 | ||
|
|
006c907da7 | ||
|
|
4f056031f4 | ||
|
|
62e73da612 | ||
|
|
ae607280c5 | ||
|
|
4a8c2229ce | ||
|
|
3116744bdd | ||
|
|
b41fc95566 | ||
|
|
00f0932760 | ||
|
|
6213d4b4b6 | ||
|
|
5a044b67bb | ||
|
|
64147b346b | ||
|
|
7c3f19c079 | ||
|
|
aa8d22e38e | ||
|
|
0a9873aa22 | ||
|
|
fb0ac27691 | ||
|
|
1e776b29d3 | ||
|
|
ba8c95a98d | ||
|
|
27d23342ea | ||
|
|
c92daa02e4 | ||
|
|
ce8d71edbc | ||
|
|
2355fc7686 | ||
|
|
d6072d3703 | ||
|
|
73a84cefda | ||
|
|
7dd792ef51 | ||
|
|
76b02c2a03 | ||
|
|
5fd6f7bd44 | ||
|
|
deb410710c | ||
|
|
1b599ea7f8 | ||
|
|
2d9b5e0bb8 | ||
|
|
83466c6151 | ||
|
|
78f288bc87 | ||
|
|
7bebf1f59a | ||
|
|
7f51aa13e7 | ||
|
|
a80acab4fc | ||
|
|
3783b33508 | ||
|
|
43a34d354a | ||
|
|
5a92536cea | ||
|
|
e263ee3cbf | ||
|
|
15e0dc08a6 | ||
|
|
256f6e6200 | ||
|
|
e8039673ad | ||
|
|
12265da6cd | ||
|
|
2c657f6608 | ||
|
|
8f7e3f325d | ||
|
|
2c6cd08bcc | ||
|
|
1300cec38c | ||
|
|
f9bf48d643 | ||
|
|
96bd8f2b25 | ||
|
|
f2698687fb | ||
|
|
5247bbc2f0 | ||
|
|
0d598aca08 | ||
|
|
23594b6980 | ||
|
|
f22e961f80 | ||
|
|
a327c7a552 | ||
|
|
4d9aaacc85 | ||
|
|
cd24bd05b4 | ||
|
|
9bcc0b970b | ||
|
|
88b3cb570e | ||
|
|
6ed868c51c | ||
|
|
e2c89576c7 | ||
|
|
c6537d11cb | ||
|
|
2eaa1104f7 | ||
|
|
265dddbecf | ||
|
|
3667408a57 | ||
|
|
5342b32eef | ||
|
|
adb1456472 | ||
|
|
6c96c41ee4 | ||
|
|
f466577673 | ||
|
|
34140dd627 | ||
|
|
b0d40c12da | ||
|
|
f99d3de221 | ||
|
|
2de1b2d14c | ||
|
|
2bcb964694 | ||
|
|
3e8b9e6d10 | ||
|
|
d778bde7f9 | ||
|
|
54bf8c0556 | ||
|
|
2bcc187b1b | ||
|
|
d13aa5426a | ||
|
|
7097268ac5 | ||
|
|
84f4e99635 | ||
|
|
8b0c4c6582 | ||
|
|
fb2c34f8cd | ||
|
|
65b974e396 | ||
|
|
365d0ad545 | ||
|
|
52b7254b9c | ||
|
|
0bea5c7f21 | ||
|
|
24a19cc37e | ||
|
|
38d2e8b9d8 | ||
|
|
3b8cd565be | ||
|
|
200b58dad8 | ||
|
|
6ca0299e5b | ||
|
|
5487bc23c8 | ||
|
|
aee0da0b17 | ||
|
|
6d66b5a971 | ||
|
|
8ba48f84fe | ||
|
|
62c5a5466a | ||
|
|
7bc5e51847 | ||
|
|
7b8e283980 | ||
|
|
e9c64e3f47 | ||
|
|
81f957ae09 | ||
|
|
3ba1190eb4 | ||
|
|
6f8b8887b1 | ||
|
|
bb24eb9de4 | ||
|
|
44738b516a | ||
|
|
c42532c37d | ||
|
|
b0b8ac13ce | ||
|
|
16559cd60c | ||
|
|
4386b4566b | ||
|
|
4d7eadb2fa | ||
|
|
c262e9ea04 | ||
|
|
b78d3ff1dc | ||
|
|
f6db2edc40 | ||
|
|
0c7f0ed312 | ||
|
|
fe9b1f60ce | ||
|
|
09f4ce9857 | ||
|
|
484ee920c1 | ||
|
|
debf0234cc | ||
|
|
58f6207abe | ||
|
|
5556cf1565 | ||
|
|
6144d43321 | ||
|
|
c897c52088 | ||
|
|
ce93d5440f | ||
|
|
02af482c32 | ||
|
|
7baf968102 | ||
|
|
acc4f88e6d | ||
|
|
4821702fb4 | ||
|
|
d733dc752e | ||
|
|
ef156f0c44 | ||
|
|
0bca832c18 | ||
|
|
44211ddff5 | ||
|
|
8f2d519203 | ||
|
|
9825011ced | ||
|
|
2c538d7a2b | ||
|
|
bdd09709d7 | ||
|
|
fc72e41a55 | ||
|
|
6ab1140623 | ||
|
|
0b8d7f44b4 | ||
|
|
27feb1adac | ||
|
|
1c1919072b | ||
|
|
be5e9cb962 | ||
|
|
48c85f1b15 | ||
|
|
398e22c541 | ||
|
|
6bbfb8f610 | ||
|
|
1d0e5e8b01 | ||
|
|
1e1d3ff687 | ||
|
|
736b565766 | ||
|
|
c2ec76a41f | ||
|
|
6b52984ce4 | ||
|
|
c9c05ca5f0 | ||
|
|
32ba2eadf6 | ||
|
|
3e74b91de6 | ||
|
|
e657dfb491 | ||
|
|
2a6c104722 | ||
|
|
38e8a23025 | ||
|
|
bb07bf31aa | ||
|
|
eb79471184 | ||
|
|
59c3563827 | ||
|
|
45466d2df6 | ||
|
|
807321efba | ||
|
|
ff3a5daf25 | ||
|
|
0bd402d2eb | ||
|
|
9668499b9f | ||
|
|
72a88fbab0 | ||
|
|
4d9f6d2bcf | ||
|
|
d65463809c | ||
|
|
62f99adb71 | ||
|
|
aa7ef7919e | ||
|
|
13affef3f1 | ||
|
|
c50af8399d | ||
|
|
ec7d36326d | ||
|
|
bf45336afb | ||
|
|
6e5b1cc43a | ||
|
|
3bd3c71fd1 | ||
|
|
79c72b2419 | ||
|
|
df36de6507 | ||
|
|
c52df4de38 | ||
|
|
8da6027e73 | ||
|
|
c1265d1616 | ||
|
|
22d8df96c6 | ||
|
|
8da2d689df | ||
|
|
fe203057c2 | ||
|
|
114883e078 | ||
|
|
7a5123a770 | ||
|
|
4df5bd2eb0 |
37
.cvsignore → .gitignore
vendored
37
.cvsignore → .gitignore
vendored
@@ -1,40 +1,33 @@
|
||||
*.o
|
||||
*.a
|
||||
tcc_g
|
||||
tcc
|
||||
/*-tcc
|
||||
tc2.c
|
||||
ex3
|
||||
otcc1.c
|
||||
doc
|
||||
tc3s.c
|
||||
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
|
||||
tcc-newparse.c
|
||||
p1.c
|
||||
Makefile.uClibc
|
||||
boundtest
|
||||
p4.c
|
||||
p5.c
|
||||
prog.ref
|
||||
test.ref
|
||||
a.c
|
||||
p3
|
||||
test.out
|
||||
elf.h
|
||||
stab.h
|
||||
stab.def
|
||||
p2
|
||||
tcc-doc.html
|
||||
ideas
|
||||
tcctest.ref
|
||||
test
|
||||
linux.tcc
|
||||
wintest.c
|
||||
ldtest
|
||||
libtcc_test
|
||||
instr.S
|
||||
@@ -42,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
|
||||
gcctestsuite.sh
|
||||
tags
|
||||
.DS_Store
|
||||
*.swp
|
||||
lib/x86_64
|
||||
lib/i386
|
||||
lib/x86_64-win32
|
||||
lib/i386-win32
|
||||
tcc-doc.info
|
||||
conftest*
|
||||
tiny_libmaker
|
||||
*.dSYM
|
||||
154
Changelog
154
Changelog
@@ -1,3 +1,157 @@
|
||||
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)
|
||||
- support µClibc
|
||||
- split tcc.c into tcc.h libtcc.c tccpp.c tccgen.c tcc.c
|
||||
- improved preprocess output with linenumbers and spaces preserved
|
||||
- tcc_relocate now copies code into user buffer
|
||||
- fix bitfields with non-int types and in unions
|
||||
- improve ARM cross-compiling (Daniel Glöckner)
|
||||
- link stabstr sections from multiple objects
|
||||
- better (still limited) support for multiple TCCStates
|
||||
|
||||
version 0.9.24:
|
||||
|
||||
- added verbosity levels -v, -vv, -vvv
|
||||
- Accept standard input as an inputstream (Hanzac Chen)
|
||||
- Support c89 compilers other than gcc (Hanzac Chen)
|
||||
- -soname linker option (Marc Andre Tanner)
|
||||
- Just warn about unknown directives, ignore quotes in #error/#warning
|
||||
- Define __STDC_VERSION__=199901L (477)
|
||||
- Switch to newer tccpe.c (includes support for resources)
|
||||
- Handle backslashes within #include/#error/#warning
|
||||
- Import changesets (part 4) 428,457,460,467: defines for openbsd etc.
|
||||
- Use _WIN32 for a windows hosted tcc and define it for the PE target,
|
||||
otherwise define __unix / __linux (Detlef Riekenberg)
|
||||
- Import changesets (part 3) 409,410: ARM EABI by Daniel Glöckner
|
||||
- Some in-between fixes:
|
||||
TCC -E no longer hangs with macro calls involving newlines.
|
||||
(next_nomacro1 now advances the read-pointer with TOK_LINEFEED)
|
||||
Global cast (int g_i = 1LL;) no longer crashes tcc.
|
||||
(nocode_wanted is initially 1, and only 0 for gen_function)
|
||||
On win32 now tcc.exe finds 'include' & 'lib' even if itself is in 'bin'.
|
||||
(new function w32_tcc_lib_path removes 'bin' if detected)
|
||||
Added quick build batch file for mingw (win32/build-tcc.bat)
|
||||
Last added case label optimization (455) produced wrong code. Reverted.
|
||||
|
||||
- Import more changesets from Rob Landley's fork (part 2):
|
||||
487: Handle long long constants in gen_opic() (Rob Landley)
|
||||
484: Handle parentheses within __attribute__((...)) (Rob Landley)
|
||||
480: Remove a goto in decl_initializer_alloc (Rob Landley)
|
||||
475: Fix dereferences in inline assembly output (Joshua Phillips)
|
||||
474: Cast ptrs to ints of different sizes correctly (Joshua Phillips)
|
||||
473: Fix size of structs with empty array member (Joshua Phillips)
|
||||
470: No warning for && and || with mixed pointers/integers (Rob Landley)
|
||||
469: Fix symbol visibility problems in the linker (Vincent Pit)
|
||||
468: Allow && and || involving pointer arguments (Rob Landley)
|
||||
455: Optimize case labels with no code in between (Zdenek Pavlas)
|
||||
450: Implement alloca for x86 (grischka)
|
||||
415: Parse unicode escape sequences (Axel Liljencrantz)
|
||||
407: Add a simple va_copy() in stdarg.h (Hasso Tepper)
|
||||
400: Allow typedef names as symbols (Dave Dodge)
|
||||
|
||||
- Import some changesets from Rob Landley's fork (part 1):
|
||||
462: Use LGPL with bcheck.c and il-gen.c
|
||||
458: Fix global compound literals (in unary: case '&':) (Andrew Johnson)
|
||||
456: Use return code from tcc_output_file in main() (Michael Somos)
|
||||
442: Fix indirections with function pointers (***fn)() (grischka)
|
||||
441: Fix LL left shift in libtcc1.c:__shldi3 (grischka)
|
||||
440: Pass structures and function ptrs through ?: (grischka)
|
||||
439: Keep rvalue in bit assignment (bit2 = bit1 = x) (grischka)
|
||||
438: Degrade nonportable pointer assignment to warning (grischka)
|
||||
437: Call 'saveregs()' before jumping with logical and/or/not (grischka)
|
||||
435: Put local static variables into global memory (grischka)
|
||||
432/434: Cast double and ptr to bool (grischka)
|
||||
420: Zero pad x87 tenbyte long doubles (Felix Nawothnig)
|
||||
417: Make 'sizeof' unsigned (Rob Landley)
|
||||
397: Fix save_reg for longlongs (Daniel Glöckner)
|
||||
396: Fix "invalid relocation entry" problem on ubuntu - (Bernhard Fischer)
|
||||
|
||||
- ignore AS_NEEDED ld command
|
||||
- mark executable sections as executable when running in memory
|
||||
- added support for win32 wchar_t (Filip Navara)
|
||||
- segment override prefix support (Filip Navara)
|
||||
- normalized slashes in paths (Filip Navara)
|
||||
- windows style fastcall (Filip Navara)
|
||||
- support for empty input register section in asm (Filip Navara)
|
||||
- anonymous union/struct support (Filip Navara)
|
||||
- fixed parsing of function parameters
|
||||
- workaround for function pointers in conditional expressions (Dave Dodge)
|
||||
- initial '-E' option support to use the C preprocessor alone
|
||||
- discard type qualifiers when comparing function parameters (Dave Dodge)
|
||||
- Bug fix: A long long value used as a test expression ignores the
|
||||
upper 32 bits at runtime (Dave Dodge)
|
||||
- fixed multiple concatenation of PPNUM tokens (initial patch by Dave Dodge)
|
||||
- fixed multiple typedef specifiers handling
|
||||
- fixed sign extension in some type conversions (Dave Dodge)
|
||||
|
||||
version 0.9.23:
|
||||
|
||||
- initial PE executable format for windows version (grischka)
|
||||
- '#pragma pack' support (grischka)
|
||||
- '#include_next' support (Bernhard Fischer)
|
||||
- ignore '-pipe' option
|
||||
- added -f[no-]leading-underscore
|
||||
- preprocessor function macro parsing fix (grischka)
|
||||
|
||||
version 0.9.22:
|
||||
|
||||
- simple memory optimisations: kernel compilation is 30% faster
|
||||
- linker symbol definitions fixes
|
||||
- gcc 3.4 fixes
|
||||
- fixed value stack full error
|
||||
- 'packed' attribute support for variables and structure fields
|
||||
- ignore 'const' and 'volatile' in function prototypes
|
||||
- allow '_Bool' in bit fields
|
||||
|
||||
version 0.9.21:
|
||||
|
||||
- ARM target support (Daniel Glöckner)
|
||||
- added '-funsigned-char, '-fsigned-char' and
|
||||
'-Wimplicit-function-declaration'
|
||||
- fixed assignment of const struct in struct
|
||||
- line comment fix (reported by Bertram Felgenhauer)
|
||||
- initial TMS320C67xx target support (TK)
|
||||
- win32 configure
|
||||
- regparm() attribute
|
||||
- many built-in assembler fixes
|
||||
- added '.org', '.fill' and '.previous' assembler directives
|
||||
- '-fno-common' option
|
||||
- '-Ttext' linker option
|
||||
- section alignment fixes
|
||||
- bit fields fixes
|
||||
- do not generate code for unused inline functions
|
||||
- '-oformat' linker option.
|
||||
- added 'binary' output format.
|
||||
|
||||
version 0.9.20:
|
||||
|
||||
- added '-w' option
|
||||
|
||||
491
Makefile
491
Makefile
@@ -1,234 +1,349 @@
|
||||
#
|
||||
# Tiny C Compiler Makefile
|
||||
#
|
||||
include config.mak
|
||||
|
||||
CFLAGS=-O2 -g -Wall
|
||||
LIBS=-ldl
|
||||
CFLAGS_P=$(CFLAGS) -pg -static -DCONFIG_TCC_STATIC
|
||||
LIBS_P=
|
||||
TOP ?= .
|
||||
include $(TOP)/config.mak
|
||||
VPATH = $(top_srcdir)
|
||||
|
||||
CFLAGS+=-mpreferred-stack-boundary=2
|
||||
ifeq ($(GCC_MAJOR),2)
|
||||
CFLAGS+=-m386 -malign-functions=0
|
||||
CPPFLAGS = -I$(TOP) # for config.h
|
||||
|
||||
ifeq (-$(findstring gcc,$(CC))-,-gcc-)
|
||||
ifeq (-$(findstring $(GCC_MAJOR),01)-,--)
|
||||
CFLAGS+=-fno-strict-aliasing
|
||||
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
|
||||
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
|
||||
|
||||
DISAS=objdump -d
|
||||
INSTALL=install
|
||||
CPPFLAGS_P=$(CPPFLAGS) -DCONFIG_TCC_STATIC
|
||||
CFLAGS_P=$(CFLAGS) -pg -static
|
||||
LIBS_P=
|
||||
LDFLAGS_P=$(LDFLAGS)
|
||||
|
||||
# run local version of tcc with local libraries and includes
|
||||
TCC=./tcc -B. -I.
|
||||
ifdef CONFIG_WIN64
|
||||
CONFIG_WIN32=yes
|
||||
endif
|
||||
|
||||
all: tcc libtcc1.a bcheck.o tcc-doc.html tcc.1 libtcc.a libtcc_test
|
||||
ifndef CONFIG_WIN32
|
||||
LIBS=-lm
|
||||
ifndef CONFIG_NOLDL
|
||||
LIBS+=-ldl
|
||||
endif
|
||||
endif
|
||||
|
||||
Makefile: config.mak
|
||||
# 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
|
||||
|
||||
# auto test
|
||||
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)
|
||||
|
||||
test: test.ref test.out
|
||||
@if diff -u test.ref test.out ; then echo "Auto Test OK"; fi
|
||||
ifeq ($(TOP),.)
|
||||
|
||||
tcctest.ref: tcctest.c
|
||||
$(CC) $(CFLAGS) -I. -o $@ $<
|
||||
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)
|
||||
|
||||
test.ref: tcctest.ref
|
||||
./tcctest.ref > $@
|
||||
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
|
||||
|
||||
test.out: tcc tcctest.c
|
||||
$(TCC) -run tcctest.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
|
||||
|
||||
run: tcc tcctest.c
|
||||
$(TCC) -run tcctest.c
|
||||
ifeq ($(TARGETOS),Darwin)
|
||||
PROGS+=tiny_libmaker$(EXESUF)
|
||||
endif
|
||||
|
||||
# iterated test2 (compile tcc then compile tcctest.c !)
|
||||
test2: tcc tcc.c tcctest.c test.ref
|
||||
$(TCC) -run tcc.c -B. -I. -run tcctest.c > test.out2
|
||||
@if diff -u test.ref test.out2 ; then echo "Auto Test2 OK"; fi
|
||||
ifdef CONFIG_USE_LIBGCC
|
||||
LIBTCC1=
|
||||
endif
|
||||
|
||||
# iterated test3 (compile tcc then compile tcc then compile tcctest.c !)
|
||||
test3: tcc tcc.c tcctest.c test.ref
|
||||
$(TCC) -run tcc.c -B. -I. -run tcc.c -B. -I. -run tcctest.c > test.out3
|
||||
@if diff -u test.ref test.out3 ; then echo "Auto Test3 OK"; fi
|
||||
TCCLIBS = $(LIBTCC1) $(LIBTCC)
|
||||
TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
|
||||
|
||||
# binary output test
|
||||
test4: tcc test.ref
|
||||
# dynamic output
|
||||
$(TCC) -o tcctest1 tcctest.c
|
||||
./tcctest1 > test1.out
|
||||
@if diff -u test.ref test1.out ; then echo "Dynamic 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
|
||||
# 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
|
||||
# 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
|
||||
ifdef CONFIG_CROSS
|
||||
PROGS+=$(PROGS_CROSS)
|
||||
TCCLIBS+=$(LIBTCC1_CROSS)
|
||||
endif
|
||||
|
||||
# memory and bound check auto test
|
||||
BOUNDS_OK = 1 4 8 10
|
||||
BOUNDS_FAIL= 2 5 7 9 11 12 13
|
||||
all: $(PROGS) $(TCCLIBS) $(TCCDOCS)
|
||||
|
||||
btest: boundtest.c tcc
|
||||
@for i in $(BOUNDS_OK); do \
|
||||
if $(TCC) -b -run boundtest.c $$i ; then \
|
||||
/bin/true ; \
|
||||
else\
|
||||
echo Failed positive test $$i ; exit 1 ; \
|
||||
fi ;\
|
||||
done ;\
|
||||
for i in $(BOUNDS_FAIL); do \
|
||||
if $(TCC) -b -run boundtest.c $$i ; then \
|
||||
echo Failed negative test $$i ; exit 1 ;\
|
||||
else\
|
||||
/bin/true ; \
|
||||
fi\
|
||||
done ;\
|
||||
echo Bound test OK
|
||||
# Host Tiny C Compiler
|
||||
tcc$(EXESUF): tcc.o $(LIBTCC)
|
||||
$(CC) -o $@ $^ $(LIBS) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LINK_LIBTCC)
|
||||
|
||||
# speed test
|
||||
speed: tcc ex2 ex3
|
||||
time ./ex2 1238 2 3 4 10 13 4
|
||||
time ./tcc -I. ./ex2.c 1238 2 3 4 10 13 4
|
||||
time ./ex3 35
|
||||
time ./tcc -I. ./ex3.c 35
|
||||
|
||||
ex2: ex2.c
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
ex3: ex3.c
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
# Native Tiny C Compiler
|
||||
|
||||
tcc_g: tcc.c i386-gen.c tccelf.c tccasm.c i386-asm.c tcctok.h libtcc.h i386-asm.h Makefile
|
||||
$(CC) $(CFLAGS) -o $@ $< $(LIBS)
|
||||
|
||||
tcc: tcc_g Makefile
|
||||
strip -s -R .comment -R .note -o $@ $<
|
||||
|
||||
# TinyCC runtime libraries
|
||||
libtcc1.o: libtcc1.c
|
||||
$(CC) -O2 -Wall -c -o $@ $<
|
||||
|
||||
libtcc1.a: libtcc1.o
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
bcheck.o: bcheck.c
|
||||
$(CC) -O2 -Wall -c -o $@ $<
|
||||
|
||||
install: tcc_install libinstall
|
||||
|
||||
tcc_install: tcc tcc.1 libtcc1.a bcheck.o
|
||||
$(INSTALL) -m755 tcc $(bindir)
|
||||
$(INSTALL) tcc.1 $(mandir)/man1
|
||||
mkdir -p $(libdir)/tcc
|
||||
mkdir -p $(libdir)/tcc/include
|
||||
$(INSTALL) -m644 libtcc1.a bcheck.o $(libdir)/tcc
|
||||
$(INSTALL) -m644 stdarg.h stddef.h stdbool.h float.h varargs.h \
|
||||
tcclib.h $(libdir)/tcc/include
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o tcc tcc1 tcct tcc_g tcctest.ref *.bin *.i ex2 \
|
||||
core gmon.out test.out test.ref a.out tcc_p \
|
||||
*.exe tcc-doc.html tcc.pod tcc.1 libtcc.a libtcc_test \
|
||||
tcctest[1234] test[1234].out
|
||||
|
||||
distclean: clean
|
||||
rm -f config.h config.mak config.texi
|
||||
|
||||
# win32 TCC
|
||||
tcc_g.exe: tcc.c i386-gen.c bcheck.c Makefile
|
||||
i386-mingw32msvc-gcc $(CFLAGS) -DCONFIG_TCC_STATIC -o $@ $<
|
||||
|
||||
tcc.exe: tcc_g.exe
|
||||
i386-mingw32msvc-strip -o $@ $<
|
||||
# Cross Tiny C Compilers
|
||||
%-tcc$(EXESUF): tcc.c
|
||||
$(CC) -o $@ $< -DONE_SOURCE $(DEFINES) $(CPPFLAGS) $(CFLAGS) $(LIBS) $(LDFLAGS)
|
||||
|
||||
# profiling version
|
||||
tcc_p: tcc.c Makefile
|
||||
$(CC) $(CFLAGS_P) -o $@ $< $(LIBS_P)
|
||||
tcc_p$(EXESUF): $(NATIVE_FILES)
|
||||
$(CC) -o $@ $< -DONE_SOURCE $(NATIVE_DEFINES) $(CPPFLAGS_P) $(CFLAGS_P) $(LIBS_P) $(LDFLAGS_P)
|
||||
|
||||
# libtcc generation and example
|
||||
libinstall: libtcc.a
|
||||
$(INSTALL) -m644 libtcc.a $(libdir)
|
||||
$(INSTALL) -m644 libtcc.h $(includedir)
|
||||
$(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
|
||||
|
||||
libtcc.o: tcc.c i386-gen.c bcheck.c Makefile
|
||||
$(CC) $(CFLAGS) -DLIBTCC -c -o $@ $<
|
||||
$(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.a: libtcc.o
|
||||
# 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_test: libtcc_test.c libtcc.a
|
||||
$(CC) $(CFLAGS) -I. -o $@ $< -L. -ltcc -ldl
|
||||
libtcc.so.1.0: $(LIBTCC_OBJ)
|
||||
$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDFLAGS)
|
||||
|
||||
libtest: libtcc_test
|
||||
./libtcc_test
|
||||
libtcc.so.1.0: CFLAGS+=-fPIC
|
||||
|
||||
# targets for development
|
||||
# windows utilities
|
||||
tiny_impdef$(EXESUF): win32/tools/tiny_impdef.c
|
||||
$(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
|
||||
tiny_libmaker$(EXESUF): win32/tools/tiny_libmaker.c
|
||||
$(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
%.bin: %.c tcc
|
||||
$(TCC) -g -o $@ $<
|
||||
$(DISAS) $@
|
||||
# TinyCC runtime libraries
|
||||
libtcc1.a : FORCE
|
||||
$(MAKE) -C lib native
|
||||
lib/%/libtcc1.a : FORCE $(PROGS_CROSS)
|
||||
$(MAKE) -C lib cross TARGET=$*
|
||||
|
||||
instr: instr.o
|
||||
objdump -d instr.o
|
||||
FORCE:
|
||||
|
||||
# tiny assembler testing
|
||||
# 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
|
||||
|
||||
asmtest.ref: asmtest.S
|
||||
$(CC) -c -o asmtest.ref.o asmtest.S
|
||||
objdump -D asmtest.ref.o > $@
|
||||
ifndef CONFIG_WIN32
|
||||
install: $(PROGS) $(TCCLIBS) $(TCCDOCS)
|
||||
mkdir -p "$(bindir)"
|
||||
ifeq ($(CC),tcc)
|
||||
$(INSTALL) -m755 $(PROGS) "$(bindir)"
|
||||
else
|
||||
$(INSTALLBIN) -m755 $(PROGS) "$(bindir)"
|
||||
endif
|
||||
mkdir -p "$(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
|
||||
$(INSTALL) -m644 $(addprefix $(top_srcdir)/include/,$(TCC_INCLUDES)) "$(tccdir)/include"
|
||||
mkdir -p "$(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 $(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
|
||||
|
||||
# XXX: we compute tcc.c to go faster during development !
|
||||
asmtest.out: asmtest.S tcc
|
||||
# ./tcc tcc.c -c asmtest.S
|
||||
#asmtest.out: asmtest.S tcc
|
||||
./tcc -c asmtest.S
|
||||
objdump -D asmtest.o > $@
|
||||
uninstall:
|
||||
rm -fv $(foreach P,$(PROGS),"$(bindir)/$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" "$(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
|
||||
# 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"
|
||||
$(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 tcc-doc.html win32/tcc-win32.txt "$(tccdir)/doc"
|
||||
$(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
|
||||
|
||||
asmtest: asmtest.out asmtest.ref
|
||||
@if diff -u --ignore-matching-lines="file format" asmtest.ref asmtest.out ; then echo "ASM Auto Test OK"; fi
|
||||
|
||||
instr.o: instr.S
|
||||
$(CC) -O2 -Wall -g -c -o $@ $<
|
||||
|
||||
cache: tcc_g
|
||||
cachegrind ./tcc_g -o /tmp/linpack -lm bench/linpack.c
|
||||
vg_annotate tcc.c > /tmp/linpack.cache.log
|
||||
uninstall:
|
||||
rm -rfv "$(tccdir)/*"
|
||||
endif
|
||||
|
||||
# documentation and man page
|
||||
tcc-doc.html: tcc-doc.texi
|
||||
texi2html -monolithic -number $<
|
||||
-texi2html -monolithic -number $<
|
||||
|
||||
tcc.1: tcc-doc.texi
|
||||
./texi2pod.pl $< tcc.pod
|
||||
pod2man --section=1 --center=" " --release=" " tcc.pod > $@
|
||||
-$(top_srcdir)/texi2pod.pl $< tcc.pod
|
||||
-pod2man --section=1 --center=" " --release=" " tcc.pod > $@
|
||||
|
||||
FILES= Makefile Makefile.uClibc configure VERSION \
|
||||
README TODO COPYING \
|
||||
Changelog tcc-doc.texi tcc-doc.html \
|
||||
tcc.1 \
|
||||
tcc.c i386-gen.c tccelf.c tcctok.h tccasm.c i386-asm.c i386-asm.h\
|
||||
bcheck.c libtcc1.c \
|
||||
elf.h stab.h stab.def \
|
||||
stddef.h stdarg.h stdbool.h float.h varargs.h \
|
||||
tcclib.h libtcc.h libtcc_test.c \
|
||||
ex1.c ex2.c ex3.c ex4.c ex5.c \
|
||||
tcctest.c boundtest.c gcctestsuite.sh texi2pod.pl
|
||||
tcc-doc.info: tcc-doc.texi
|
||||
-makeinfo $<
|
||||
|
||||
FILE=tcc-$(VERSION)
|
||||
# in tests subdir
|
||||
export LIBTCC1
|
||||
|
||||
tar:
|
||||
rm -rf /tmp/$(FILE)
|
||||
mkdir -p /tmp/$(FILE)
|
||||
cp -P $(FILES) /tmp/$(FILE)
|
||||
( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) )
|
||||
rm -rf /tmp/$(FILE)
|
||||
%est:
|
||||
$(MAKE) -C tests $@
|
||||
|
||||
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.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),.)
|
||||
|
||||
19
README
19
README
@@ -28,15 +28,23 @@ Features:
|
||||
Documentation:
|
||||
-------------
|
||||
|
||||
1) Installation
|
||||
|
||||
*** TCC currently only works on Linux x86 with glibc >= 2.1 ***.
|
||||
1) Installation on a i386 Linux host (for Windows read tcc-win32.txt)
|
||||
|
||||
./configure
|
||||
make
|
||||
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.
|
||||
|
||||
@@ -67,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.
|
||||
|
||||
@@ -81,6 +90,8 @@ when doing 'make test'.
|
||||
|
||||
Please read tcc-doc.html to have all the features of TCC.
|
||||
|
||||
Additional information is available for the Windows port in tcc-win32.txt.
|
||||
|
||||
License:
|
||||
-------
|
||||
|
||||
|
||||
74
TODO
74
TODO
@@ -1,55 +1,63 @@
|
||||
TODO list:
|
||||
|
||||
Bugs:
|
||||
|
||||
- fix macro substitution with nested definitions (ShangHongzhang)
|
||||
- FPU st(0) is left unclean (kwisatz haderach). Incompatible with
|
||||
optimized gcc/msc code
|
||||
|
||||
- constructors
|
||||
- cast bug (Peter Wang)
|
||||
- define incomplete type if defined several times (Peter Wang).
|
||||
- long long constant evaluation
|
||||
- configure --cc=tcc (still one bug in libtcc1.c)
|
||||
- disable-asm and disable-bcheck options
|
||||
- test binutils/gcc compile
|
||||
- add alloca(), __builtin_expect()
|
||||
- gcc '-E' option.
|
||||
- optimize VT_LOCAL + const
|
||||
- tci patch + argument.
|
||||
- '-b' bug.
|
||||
- atexit (Nigel Horne)
|
||||
- see -lxxx bug (Michael Charity).
|
||||
- handle inline functions as macros.
|
||||
- see transparent union pb in /urs/include/sys/socket.h
|
||||
- precise behaviour of typeof with arrays ? (__put_user macro)
|
||||
- #include_next support for /usr/include/limits ?
|
||||
but should suffice for most cases)
|
||||
- handle '? x, y : z' in unsized variable initialization (',' is
|
||||
considered incorrectly as separator in preparser)
|
||||
- function pointers/lvalues in ? : (linux kernel net/core/dev.c)
|
||||
- transform functions to function pointers in function parameters (net/ipv4/ip_output.c)
|
||||
- transform functions to function pointers in function parameters
|
||||
(net/ipv4/ip_output.c)
|
||||
- fix function pointer type display
|
||||
- fix bound exit on RedHat 7.3
|
||||
- check lcc test suite -> fix bitfield binary operations
|
||||
- check section alignment in C
|
||||
- fix invalid cast in comparison 'if (v == (int8_t)v)'
|
||||
- packed attribute
|
||||
- finish varargs.h support (gcc 3.2 testsuite issue)
|
||||
- fix static functions declared inside block
|
||||
- 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)
|
||||
- fix multiple unions init
|
||||
- setjmp is not supported properly in bound checking.
|
||||
- better local variables handling (needed for other targets)
|
||||
- fix bound check code with '&' on local variables (currently done
|
||||
only for local arrays).
|
||||
- sizeof, alignof, typeof can still generate code in some cases.
|
||||
- bound checking and float/long long/struct copy code. bound
|
||||
checking and symbol + offset optimization
|
||||
- Fix the remaining libtcc memory leaks.
|
||||
- make libtcc fully reentrant (except for the compilation stage itself).
|
||||
- '-MD' option
|
||||
|
||||
Bound checking:
|
||||
|
||||
- '-b' bug.
|
||||
- fix bound exit on RedHat 7.3
|
||||
- setjmp is not supported properly in bound checking.
|
||||
- fix bound check code with '&' on local variables (currently done
|
||||
only for local arrays).
|
||||
- bound checking and float/long long/struct copy code. bound
|
||||
checking and symbol + offset optimization
|
||||
|
||||
Missing features:
|
||||
|
||||
- disable-asm and disable-bcheck options
|
||||
- __builtin_expect()
|
||||
- improve '-E' option.
|
||||
- atexit (Nigel Horne)
|
||||
- packed attribute
|
||||
- C99: add complex types (gcc 3.2 testsuite issue)
|
||||
- postfix compound literals (see 20010124-1.c)
|
||||
|
||||
Optimizations:
|
||||
|
||||
- suppress specific anonymous symbol handling
|
||||
- more parse optimizations (=even faster compilation)
|
||||
- memory alloc optimizations (=even faster compilation)
|
||||
- optimize VT_LOCAL + const
|
||||
- better local variables handling (needed for other targets)
|
||||
|
||||
Not critical:
|
||||
|
||||
@@ -65,11 +73,21 @@ Not critical:
|
||||
- add portable byte code generator and interpreter for other
|
||||
unsupported architectures.
|
||||
- C++: variable declaration in for, minimal 'class' support.
|
||||
- win32: add __stdcall, __intxx. use resolve for bchecked malloc et
|
||||
al. check GetModuleHandle for dlls. check exception code (exception
|
||||
filter func).
|
||||
- win32: __intxx. use resolve for bchecked malloc et al.
|
||||
check exception code (exception filter func).
|
||||
- handle void (__attribute__() *ptr)()
|
||||
|
||||
Fixed (probably):
|
||||
|
||||
|
||||
|
||||
- bug with defines:
|
||||
#define spin_lock(lock) do { } while (0)
|
||||
#define wq_spin_lock spin_lock
|
||||
#define TEST() wq_spin_lock(a)
|
||||
- typedefs can be structure fields
|
||||
- see bugfixes.diff + improvement.diff from Daniel Glockner
|
||||
- long long constant evaluation
|
||||
- add alloca()
|
||||
- gcc '-E' option.
|
||||
- #include_next support for /usr/include/limits ?
|
||||
- function pointers/lvalues in ? : (linux kernel net/core/dev.c)
|
||||
- win32: add __stdcall, check GetModuleHandle for dlls.
|
||||
|
||||
446
coff.h
Normal file
446
coff.h
Normal file
@@ -0,0 +1,446 @@
|
||||
/**************************************************************************/
|
||||
/* COFF.H */
|
||||
/* COFF data structures and related definitions used by the linker */
|
||||
/**************************************************************************/
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* COFF FILE HEADER */
|
||||
/*------------------------------------------------------------------------*/
|
||||
struct filehdr {
|
||||
unsigned short f_magic; /* magic number */
|
||||
unsigned short f_nscns; /* number of sections */
|
||||
long f_timdat; /* time & date stamp */
|
||||
long f_symptr; /* file pointer to symtab */
|
||||
long f_nsyms; /* number of symtab entries */
|
||||
unsigned short f_opthdr; /* sizeof(optional hdr) */
|
||||
unsigned short f_flags; /* flags */
|
||||
unsigned short f_TargetID; /* for C6x = 0x0099 */
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* File header flags */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define F_RELFLG 0x01 /* relocation info stripped from file */
|
||||
#define F_EXEC 0x02 /* file is executable (no unresolved refs) */
|
||||
#define F_LNNO 0x04 /* line nunbers stripped from file */
|
||||
#define F_LSYMS 0x08 /* local symbols stripped from file */
|
||||
#define F_GSP10 0x10 /* 34010 version */
|
||||
#define F_GSP20 0x20 /* 34020 version */
|
||||
#define F_SWABD 0x40 /* bytes swabbed (in names) */
|
||||
#define F_AR16WR 0x80 /* byte ordering of an AR16WR (PDP-11) */
|
||||
#define F_LITTLE 0x100 /* byte ordering of an AR32WR (vax) */
|
||||
#define F_BIG 0x200 /* byte ordering of an AR32W (3B, maxi) */
|
||||
#define F_PATCH 0x400 /* contains "patch" list in optional header */
|
||||
#define F_NODF 0x400
|
||||
|
||||
#define F_VERSION (F_GSP10 | F_GSP20)
|
||||
#define F_BYTE_ORDER (F_LITTLE | F_BIG)
|
||||
#define FILHDR struct filehdr
|
||||
|
||||
//#define FILHSZ sizeof(FILHDR)
|
||||
#define FILHSZ 22 // above rounds to align on 4 bytes which causes problems
|
||||
|
||||
#define COFF_C67_MAGIC 0x00c2
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Macros to recognize magic numbers */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define ISMAGIC(x) (((unsigned short)(x))==(unsigned short)magic)
|
||||
#define ISARCHIVE(x) ((((unsigned short)(x))==(unsigned short)ARTYPE))
|
||||
#define BADMAGIC(x) (((unsigned short)(x) & 0x8080) && !ISMAGIC(x))
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* OPTIONAL FILE HEADER */
|
||||
/*------------------------------------------------------------------------*/
|
||||
typedef struct aouthdr {
|
||||
short magic; /* see magic.h */
|
||||
short vstamp; /* version stamp */
|
||||
long tsize; /* text size in bytes, padded to FW bdry*/
|
||||
long dsize; /* initialized data " " */
|
||||
long bsize; /* uninitialized data " " */
|
||||
long entrypt; /* entry pt. */
|
||||
long text_start; /* base of text used for this file */
|
||||
long data_start; /* base of data used for this file */
|
||||
} AOUTHDR;
|
||||
|
||||
#define AOUTSZ sizeof(AOUTHDR)
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* When a UNIX aout header is to be built in the optional header, */
|
||||
/* the following magic numbers can appear in that header: */
|
||||
/* */
|
||||
/* AOUT1MAGIC : default : readonly sharable text segment */
|
||||
/* AOUT2MAGIC: : writable text segment */
|
||||
/* PAGEMAGIC : : configured for paging */
|
||||
/*----------------------------------------------------------------------*/
|
||||
#define AOUT1MAGIC 0410
|
||||
#define AOUT2MAGIC 0407
|
||||
#define PAGEMAGIC 0413
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* COMMON ARCHIVE FILE STRUCTURES */
|
||||
/* */
|
||||
/* ARCHIVE File Organization: */
|
||||
/* _______________________________________________ */
|
||||
/* |__________ARCHIVE_MAGIC_STRING_______________| */
|
||||
/* |__________ARCHIVE_FILE_MEMBER_1______________| */
|
||||
/* | | */
|
||||
/* | Archive File Header "ar_hdr" | */
|
||||
/* |.............................................| */
|
||||
/* | Member Contents | */
|
||||
/* | 1. External symbol directory | */
|
||||
/* | 2. Text file | */
|
||||
/* |_____________________________________________| */
|
||||
/* |________ARCHIVE_FILE_MEMBER_2________________| */
|
||||
/* | "ar_hdr" | */
|
||||
/* |.............................................| */
|
||||
/* | Member Contents (.o or text file) | */
|
||||
/* |_____________________________________________| */
|
||||
/* | . . . | */
|
||||
/* | . . . | */
|
||||
/* | . . . | */
|
||||
/* |_____________________________________________| */
|
||||
/* |________ARCHIVE_FILE_MEMBER_n________________| */
|
||||
/* | "ar_hdr" | */
|
||||
/* |.............................................| */
|
||||
/* | Member Contents | */
|
||||
/* |_____________________________________________| */
|
||||
/* */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define COFF_ARMAG "!<arch>\n"
|
||||
#define SARMAG 8
|
||||
#define ARFMAG "`\n"
|
||||
|
||||
struct ar_hdr /* archive file member header - printable ascii */
|
||||
{
|
||||
char ar_name[16]; /* file member name - `/' terminated */
|
||||
char ar_date[12]; /* file member date - decimal */
|
||||
char ar_uid[6]; /* file member user id - decimal */
|
||||
char ar_gid[6]; /* file member group id - decimal */
|
||||
char ar_mode[8]; /* file member mode - octal */
|
||||
char ar_size[10]; /* file member size - decimal */
|
||||
char ar_fmag[2]; /* ARFMAG - string to end header */
|
||||
};
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* SECTION HEADER */
|
||||
/*------------------------------------------------------------------------*/
|
||||
struct scnhdr {
|
||||
char s_name[8]; /* section name */
|
||||
long s_paddr; /* physical address */
|
||||
long s_vaddr; /* virtual address */
|
||||
long s_size; /* section size */
|
||||
long s_scnptr; /* file ptr to raw data for section */
|
||||
long s_relptr; /* file ptr to relocation */
|
||||
long s_lnnoptr; /* file ptr to line numbers */
|
||||
unsigned int s_nreloc; /* number of relocation entries */
|
||||
unsigned int s_nlnno; /* number of line number entries */
|
||||
unsigned int s_flags; /* flags */
|
||||
unsigned short s_reserved; /* reserved byte */
|
||||
unsigned short s_page; /* memory page id */
|
||||
};
|
||||
|
||||
#define SCNHDR struct scnhdr
|
||||
#define SCNHSZ sizeof(SCNHDR)
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Define constants for names of "special" sections */
|
||||
/*------------------------------------------------------------------------*/
|
||||
//#define _TEXT ".text"
|
||||
#define _DATA ".data"
|
||||
#define _BSS ".bss"
|
||||
#define _CINIT ".cinit"
|
||||
#define _TV ".tv"
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* The low 4 bits of s_flags is used as a section "type" */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define STYP_REG 0x00 /* "regular" : allocated, relocated, loaded */
|
||||
#define STYP_DSECT 0x01 /* "dummy" : not allocated, relocated, not loaded */
|
||||
#define STYP_NOLOAD 0x02 /* "noload" : allocated, relocated, not loaded */
|
||||
#define STYP_GROUP 0x04 /* "grouped" : formed of input sections */
|
||||
#define STYP_PAD 0x08 /* "padding" : not allocated, not relocated, loaded */
|
||||
#define STYP_COPY 0x10 /* "copy" : used for C init tables -
|
||||
not allocated, relocated,
|
||||
loaded; reloc & lineno
|
||||
entries processed normally */
|
||||
#define STYP_TEXT 0x20 /* section contains text only */
|
||||
#define STYP_DATA 0x40 /* section contains data only */
|
||||
#define STYP_BSS 0x80 /* section contains bss only */
|
||||
|
||||
#define STYP_ALIGN 0x100 /* align flag passed by old version assemblers */
|
||||
#define ALIGN_MASK 0x0F00 /* part of s_flags that is used for align vals */
|
||||
#define ALIGNSIZE(x) (1 << ((x & ALIGN_MASK) >> 8))
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* RELOCATION ENTRIES */
|
||||
/*------------------------------------------------------------------------*/
|
||||
struct reloc
|
||||
{
|
||||
long r_vaddr; /* (virtual) address of reference */
|
||||
short r_symndx; /* index into symbol table */
|
||||
unsigned short r_disp; /* additional bits for address calculation */
|
||||
unsigned short r_type; /* relocation type */
|
||||
};
|
||||
|
||||
#define RELOC struct reloc
|
||||
#define RELSZ 10 /* sizeof(RELOC) */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* define all relocation types */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#define R_ABS 0 /* absolute address - no relocation */
|
||||
#define R_DIR16 01 /* UNUSED */
|
||||
#define R_REL16 02 /* UNUSED */
|
||||
#define R_DIR24 04 /* UNUSED */
|
||||
#define R_REL24 05 /* 24 bits, direct */
|
||||
#define R_DIR32 06 /* UNUSED */
|
||||
#define R_RELBYTE 017 /* 8 bits, direct */
|
||||
#define R_RELWORD 020 /* 16 bits, direct */
|
||||
#define R_RELLONG 021 /* 32 bits, direct */
|
||||
#define R_PCRBYTE 022 /* 8 bits, PC-relative */
|
||||
#define R_PCRWORD 023 /* 16 bits, PC-relative */
|
||||
#define R_PCRLONG 024 /* 32 bits, PC-relative */
|
||||
#define R_OCRLONG 030 /* GSP: 32 bits, one's complement direct */
|
||||
#define R_GSPPCR16 031 /* GSP: 16 bits, PC relative (in words) */
|
||||
#define R_GSPOPR32 032 /* GSP: 32 bits, direct big-endian */
|
||||
#define R_PARTLS16 040 /* Brahma: 16 bit offset of 24 bit address*/
|
||||
#define R_PARTMS8 041 /* Brahma: 8 bit page of 24 bit address */
|
||||
#define R_PARTLS7 050 /* DSP: 7 bit offset of 16 bit address */
|
||||
#define R_PARTMS9 051 /* DSP: 9 bit page of 16 bit address */
|
||||
#define R_REL13 052 /* DSP: 13 bits, direct */
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* LINE NUMBER ENTRIES */
|
||||
/*------------------------------------------------------------------------*/
|
||||
struct lineno
|
||||
{
|
||||
union
|
||||
{
|
||||
long l_symndx ; /* sym. table index of function name
|
||||
iff l_lnno == 0 */
|
||||
long l_paddr ; /* (physical) address of line number */
|
||||
} l_addr ;
|
||||
unsigned short l_lnno ; /* line number */
|
||||
};
|
||||
|
||||
#define LINENO struct lineno
|
||||
#define LINESZ 6 /* sizeof(LINENO) */
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* STORAGE CLASSES */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define C_EFCN -1 /* physical end of function */
|
||||
#define C_NULL 0
|
||||
#define C_AUTO 1 /* automatic variable */
|
||||
#define C_EXT 2 /* external symbol */
|
||||
#define C_STAT 3 /* static */
|
||||
#define C_REG 4 /* register variable */
|
||||
#define C_EXTDEF 5 /* external definition */
|
||||
#define C_LABEL 6 /* label */
|
||||
#define C_ULABEL 7 /* undefined label */
|
||||
#define C_MOS 8 /* member of structure */
|
||||
#define C_ARG 9 /* function argument */
|
||||
#define C_STRTAG 10 /* structure tag */
|
||||
#define C_MOU 11 /* member of union */
|
||||
#define C_UNTAG 12 /* union tag */
|
||||
#define C_TPDEF 13 /* type definition */
|
||||
#define C_USTATIC 14 /* undefined static */
|
||||
#define C_ENTAG 15 /* enumeration tag */
|
||||
#define C_MOE 16 /* member of enumeration */
|
||||
#define C_REGPARM 17 /* register parameter */
|
||||
#define C_FIELD 18 /* bit field */
|
||||
|
||||
#define C_BLOCK 100 /* ".bb" or ".eb" */
|
||||
#define C_FCN 101 /* ".bf" or ".ef" */
|
||||
#define C_EOS 102 /* end of structure */
|
||||
#define C_FILE 103 /* file name */
|
||||
#define C_LINE 104 /* dummy sclass for line number entry */
|
||||
#define C_ALIAS 105 /* duplicate tag */
|
||||
#define C_HIDDEN 106 /* special storage class for external */
|
||||
/* symbols in dmert public libraries */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* SYMBOL TABLE ENTRIES */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define SYMNMLEN 8 /* Number of characters in a symbol name */
|
||||
#define FILNMLEN 14 /* Number of characters in a file name */
|
||||
#define DIMNUM 4 /* Number of array dimensions in auxiliary entry */
|
||||
|
||||
|
||||
struct syment
|
||||
{
|
||||
union
|
||||
{
|
||||
char _n_name[SYMNMLEN]; /* old COFF version */
|
||||
struct
|
||||
{
|
||||
long _n_zeroes; /* new == 0 */
|
||||
long _n_offset; /* offset into string table */
|
||||
} _n_n;
|
||||
char *_n_nptr[2]; /* allows for overlaying */
|
||||
} _n;
|
||||
long n_value; /* value of symbol */
|
||||
short n_scnum; /* section number */
|
||||
unsigned short n_type; /* type and derived type */
|
||||
char n_sclass; /* storage class */
|
||||
char n_numaux; /* number of aux. entries */
|
||||
};
|
||||
|
||||
#define n_name _n._n_name
|
||||
#define n_nptr _n._n_nptr[1]
|
||||
#define n_zeroes _n._n_n._n_zeroes
|
||||
#define n_offset _n._n_n._n_offset
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Relocatable symbols have a section number of the */
|
||||
/* section in which they are defined. Otherwise, section */
|
||||
/* numbers have the following meanings: */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define N_UNDEF 0 /* undefined symbol */
|
||||
#define N_ABS -1 /* value of symbol is absolute */
|
||||
#define N_DEBUG -2 /* special debugging symbol */
|
||||
#define N_TV (unsigned short)-3 /* needs transfer vector (preload) */
|
||||
#define P_TV (unsigned short)-4 /* needs transfer vector (postload) */
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* The fundamental type of a symbol packed into the low */
|
||||
/* 4 bits of the word. */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define _EF ".ef"
|
||||
|
||||
#define T_NULL 0 /* no type info */
|
||||
#define T_ARG 1 /* function argument (only used by compiler) */
|
||||
#define T_CHAR 2 /* character */
|
||||
#define T_SHORT 3 /* short integer */
|
||||
#define T_INT 4 /* integer */
|
||||
#define T_LONG 5 /* long integer */
|
||||
#define T_FLOAT 6 /* floating point */
|
||||
#define T_DOUBLE 7 /* double word */
|
||||
#define T_STRUCT 8 /* structure */
|
||||
#define T_UNION 9 /* union */
|
||||
#define T_ENUM 10 /* enumeration */
|
||||
#define T_MOE 11 /* member of enumeration */
|
||||
#define T_UCHAR 12 /* unsigned character */
|
||||
#define T_USHORT 13 /* unsigned short */
|
||||
#define T_UINT 14 /* unsigned integer */
|
||||
#define T_ULONG 15 /* unsigned long */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* derived types are: */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define DT_NON 0 /* no derived type */
|
||||
#define DT_PTR 1 /* pointer */
|
||||
#define DT_FCN 2 /* function */
|
||||
#define DT_ARY 3 /* array */
|
||||
|
||||
#define MKTYPE(basic, d1,d2,d3,d4,d5,d6) \
|
||||
((basic) | ((d1) << 4) | ((d2) << 6) | ((d3) << 8) |\
|
||||
((d4) << 10) | ((d5) << 12) | ((d6) << 14))
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* type packing constants and macros */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define N_BTMASK_COFF 017
|
||||
#define N_TMASK_COFF 060
|
||||
#define N_TMASK1_COFF 0300
|
||||
#define N_TMASK2_COFF 0360
|
||||
#define N_BTSHFT_COFF 4
|
||||
#define N_TSHIFT_COFF 2
|
||||
|
||||
#define BTYPE_COFF(x) ((x) & N_BTMASK_COFF)
|
||||
#define ISINT(x) (((x) >= T_CHAR && (x) <= T_LONG) || \
|
||||
((x) >= T_UCHAR && (x) <= T_ULONG) || (x) == T_ENUM)
|
||||
#define ISFLT_COFF(x) ((x) == T_DOUBLE || (x) == T_FLOAT)
|
||||
#define ISPTR_COFF(x) (((x) & N_TMASK_COFF) == (DT_PTR << N_BTSHFT_COFF))
|
||||
#define ISFCN_COFF(x) (((x) & N_TMASK_COFF) == (DT_FCN << N_BTSHFT_COFF))
|
||||
#define ISARY_COFF(x) (((x) & N_TMASK_COFF) == (DT_ARY << N_BTSHFT_COFF))
|
||||
#define ISTAG_COFF(x) ((x)==C_STRTAG || (x)==C_UNTAG || (x)==C_ENTAG)
|
||||
|
||||
#define INCREF_COFF(x) ((((x)&~N_BTMASK_COFF)<<N_TSHIFT_COFF)|(DT_PTR<<N_BTSHFT_COFF)|(x&N_BTMASK_COFF))
|
||||
#define DECREF_COFF(x) ((((x)>>N_TSHIFT_COFF)&~N_BTMASK_COFF)|((x)&N_BTMASK_COFF))
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* AUXILIARY SYMBOL ENTRY */
|
||||
/*------------------------------------------------------------------------*/
|
||||
union auxent
|
||||
{
|
||||
struct
|
||||
{
|
||||
long x_tagndx; /* str, un, or enum tag indx */
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned short x_lnno; /* declaration line number */
|
||||
unsigned short x_size; /* str, union, array size */
|
||||
} x_lnsz;
|
||||
long x_fsize; /* size of function */
|
||||
} x_misc;
|
||||
union
|
||||
{
|
||||
struct /* if ISFCN, tag, or .bb */
|
||||
{
|
||||
long x_lnnoptr; /* ptr to fcn line # */
|
||||
long x_endndx; /* entry ndx past block end */
|
||||
} x_fcn;
|
||||
struct /* if ISARY, up to 4 dimen. */
|
||||
{
|
||||
unsigned short x_dimen[DIMNUM];
|
||||
} x_ary;
|
||||
} x_fcnary;
|
||||
unsigned short x_regcount; /* number of registers used by func */
|
||||
} x_sym;
|
||||
struct
|
||||
{
|
||||
char x_fname[FILNMLEN];
|
||||
} x_file;
|
||||
struct
|
||||
{
|
||||
long x_scnlen; /* section length */
|
||||
unsigned short x_nreloc; /* number of relocation entries */
|
||||
unsigned short x_nlinno; /* number of line numbers */
|
||||
} x_scn;
|
||||
};
|
||||
|
||||
#define SYMENT struct syment
|
||||
#define SYMESZ 18 /* sizeof(SYMENT) */
|
||||
|
||||
#define AUXENT union auxent
|
||||
#define AUXESZ 18 /* sizeof(AUXENT) */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* NAMES OF "SPECIAL" SYMBOLS */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define _STEXT ".text"
|
||||
#define _ETEXT "etext"
|
||||
#define _SDATA ".data"
|
||||
#define _EDATA "edata"
|
||||
#define _SBSS ".bss"
|
||||
#define _END "end"
|
||||
#define _CINITPTR "cinit"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* ENTRY POINT SYMBOLS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
#define _START "_start"
|
||||
#define _MAIN "_main"
|
||||
/* _CSTART "_c_int00" (defined in params.h) */
|
||||
|
||||
|
||||
#define _TVORIG "_tvorig"
|
||||
#define _TORIGIN "_torigin"
|
||||
#define _DORIGIN "_dorigin"
|
||||
|
||||
#define _SORIGIN "_sorigin"
|
||||
561
configure
vendored
561
configure
vendored
@@ -1,41 +1,95 @@
|
||||
#!/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
|
||||
prefix="/usr/local"
|
||||
build_cross="no"
|
||||
use_libgcc="no"
|
||||
prefix=""
|
||||
execprefix=""
|
||||
bindir=""
|
||||
libdir=""
|
||||
tccdir=""
|
||||
includedir=""
|
||||
mandir=""
|
||||
infodir=""
|
||||
sysroot=""
|
||||
cross_prefix=""
|
||||
cc="gcc"
|
||||
host_cc="gcc"
|
||||
ar="ar"
|
||||
make="make"
|
||||
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"
|
||||
;;
|
||||
armv4l)
|
||||
x86_64)
|
||||
cpu="x86-64"
|
||||
;;
|
||||
arm*)
|
||||
case "$cpu" in
|
||||
arm|armv4l)
|
||||
cpuver=4
|
||||
;;
|
||||
armv5tel|armv5tejl)
|
||||
cpuver=5
|
||||
;;
|
||||
armv6j|armv6l)
|
||||
cpuver=6
|
||||
;;
|
||||
armv7a|armv7l)
|
||||
cpuver=7
|
||||
;;
|
||||
esac
|
||||
cpu="armv4l"
|
||||
;;
|
||||
alpha)
|
||||
@@ -54,193 +108,318 @@ case "$cpu" in
|
||||
cpu="unknown"
|
||||
;;
|
||||
esac
|
||||
gprof="no"
|
||||
bigendian="no"
|
||||
|
||||
# OS specific
|
||||
targetos=`uname -s`
|
||||
case $targetos in
|
||||
*) ;;
|
||||
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`
|
||||
;;
|
||||
--cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--cc=*) cc=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--make=*) make=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
|
||||
;;
|
||||
--extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}"
|
||||
;;
|
||||
--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="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}"
|
||||
|
||||
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
|
||||
|
||||
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 ""
|
||||
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 " --cc=CC use C compiler CC [$cc]"
|
||||
echo " --make=MAKE use specified make [$make]"
|
||||
echo ""
|
||||
#echo "NOTE: The object files are build at the place where configure is launched"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test x"$execprefix" = x""; then
|
||||
execprefix="${prefix}"
|
||||
fi
|
||||
if test x"$bindir" = x""; then
|
||||
bindir="${execprefix}/bin"
|
||||
fi
|
||||
if test x"$libdir" = x""; then
|
||||
libdir="${execprefix}/lib"
|
||||
fi
|
||||
if test x"$includedir" = x""; then
|
||||
includedir="${prefix}/include"
|
||||
fi
|
||||
if test x"$mandir" = x""; then
|
||||
mandir="${prefix}/man"
|
||||
fi
|
||||
|
||||
echo "Binary directory $bindir"
|
||||
echo "Library directory $libdir"
|
||||
echo "Include directory $includedir"
|
||||
echo "Manual directory $mandir"
|
||||
echo "Source path $source_path"
|
||||
echo "C compiler $cc"
|
||||
echo "make $make"
|
||||
echo "CPU $cpu"
|
||||
echo "Big Endian $bigendian"
|
||||
echo "gprof enabled $gprof"
|
||||
|
||||
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 "libdir=$libdir" >> config.mak
|
||||
echo "includedir=$includedir" >> config.mak
|
||||
echo "mandir=$mandir" >> config.mak
|
||||
echo "#define CONFIG_TCC_LIBDIR \"$libdir\"" >> $TMPH
|
||||
echo "MAKE=$make" >> config.mak
|
||||
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 "#define GCC_MINOR $gcc_minor" >> $TMPH
|
||||
|
||||
if test "$cpu" = "x86" ; then
|
||||
echo "ARCH=i386" >> config.mak
|
||||
echo "#define HOST_I386 1" >> $TMPH
|
||||
elif test "$cpu" = "x86-64" ; then
|
||||
echo "ARCH=x86-64" >> config.mak
|
||||
echo "#define HOST_X86_64 1" >> $TMPH
|
||||
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
|
||||
@@ -257,6 +436,25 @@ 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
|
||||
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
|
||||
@@ -265,29 +463,78 @@ if test "$gprof" = "yes" ; then
|
||||
echo "TARGET_GPROF=yes" >> config.mak
|
||||
echo "#define HAVE_GPROF 1" >> $TMPH
|
||||
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
|
||||
mv -f $TMPH config.h
|
||||
mv -f $TMPH config.h
|
||||
else
|
||||
echo "config.h is unchanged"
|
||||
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;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#! /usr/local/bin/tcc -run
|
||||
#!/usr/local/bin/tcc -run
|
||||
#include <tcclib.h>
|
||||
|
||||
int main()
|
||||
int main()
|
||||
{
|
||||
printf("Hello World\n");
|
||||
return 0;
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "tcclib.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define N 20
|
||||
|
||||
@@ -23,7 +24,7 @@ int find(int n, int i1, int a, int b, int op)
|
||||
return 1;
|
||||
tab[i1] = n;
|
||||
}
|
||||
|
||||
|
||||
for(i=0;i<nb_num;i++) {
|
||||
for(j=i+1;j<nb_num;j++) {
|
||||
a = tab[i];
|
||||
@@ -52,7 +53,7 @@ int find(int n, int i1, int a, int b, int op)
|
||||
if (find(c, i, b, a, '/'))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
stack_ptr--;
|
||||
tab[i] = a;
|
||||
tab[j] = b;
|
||||
@@ -66,7 +67,7 @@ int find(int n, int i1, int a, int b, int op)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, res, p;
|
||||
|
||||
|
||||
if (argc < 3) {
|
||||
printf("usage: %s: result numbers...\n"
|
||||
"Try to find result from numbers with the 4 basic operations.\n", argv[0]);
|
||||
@@ -85,7 +86,7 @@ int main(int argc, char **argv)
|
||||
res = find(0, 0, 0, 0, ' ');
|
||||
if (res) {
|
||||
for(i=0;i<=stack_ptr;i++) {
|
||||
printf("%d %c %d = %d\n",
|
||||
printf("%d %c %d = %d\n",
|
||||
stack_res[3*i], stack_op[i],
|
||||
stack_res[3*i+1], stack_res[3*i+2]);
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <tcclib.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int fib(n)
|
||||
{
|
||||
@@ -8,7 +9,7 @@ int fib(n)
|
||||
return fib(n-1) + fib(n-2);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int n;
|
||||
if (argc < 2) {
|
||||
@@ -16,7 +17,7 @@ int main(int argc, char **argv)
|
||||
"Compute nth Fibonacci number\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
n = atoi(argv[1]);
|
||||
printf("fib(%d) = %d\n", n, fib(n, 2));
|
||||
return 0;
|
||||
@@ -1,9 +1,10 @@
|
||||
#!./tcc -run -L/usr/X11R6/lib -lX11
|
||||
#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11
|
||||
#include <stdlib.h>
|
||||
/* Yes, TCC can use X11 too ! */
|
||||
#include <stdio.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
/* Yes, TCC can use X11 too ! */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Display *display;
|
||||
@@ -16,8 +17,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
printf("X11 display opened.\n");
|
||||
screen = XScreenOfDisplay(display, 0);
|
||||
printf("width = %d\nheight = %d\ndepth = %d\n",
|
||||
screen->width,
|
||||
printf("width = %d\nheight = %d\ndepth = %d\n",
|
||||
screen->width,
|
||||
screen->height,
|
||||
screen->root_depth);
|
||||
XCloseDisplay(display);
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
int main()
|
||||
{
|
||||
printf("Hello World\n");
|
||||
return 0;
|
||||
950
i386-asm.c
950
i386-asm.c
File diff suppressed because it is too large
Load Diff
51
i386-asm.h
51
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)
|
||||
@@ -120,13 +127,13 @@ ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
|
||||
|
||||
ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
|
||||
ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
|
||||
ALT(DEF_ASM_OP1(push, 0x6a, 0, 0, OPT_IM8S))
|
||||
ALT(DEF_ASM_OP1(push, 0x68, 0, 0, OPT_IM32))
|
||||
ALT(DEF_ASM_OP1(push, 0x06, 0, 0, OPT_SEG))
|
||||
ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
|
||||
ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
|
||||
ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
|
||||
|
||||
ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
|
||||
ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
|
||||
ALT(DEF_ASM_OP1(pop, 0x07, 0, 0, OPT_SEG))
|
||||
ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
|
||||
|
||||
ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
|
||||
ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
|
||||
@@ -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)
|
||||
@@ -330,6 +343,8 @@ ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
|
||||
DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
|
||||
DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
|
||||
DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
|
||||
DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
|
||||
DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
|
||||
|
||||
/* segments */
|
||||
DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
|
||||
@@ -348,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 ))
|
||||
@@ -362,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 )
|
||||
@@ -379,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 )
|
||||
|
||||
276
i386-gen.c
276
i386-gen.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* X86 code generator for TCC
|
||||
*
|
||||
* Copyright (c) 2001, 2002, 2003 Fabrice Bellard
|
||||
* 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
|
||||
@@ -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,17 +66,43 @@ int reg_classes[NB_REGS] = {
|
||||
/* maximum alignment (for aligned attribute support) */
|
||||
#define MAX_ALIGN 8
|
||||
|
||||
/* relocation type for 32 bit data relocation */
|
||||
#define R_DATA_32 R_386_32
|
||||
|
||||
#define psym oad
|
||||
|
||||
/******************************************************/
|
||||
/* ELF defines */
|
||||
|
||||
#define EM_TCC_TARGET EM_386
|
||||
|
||||
/* 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
|
||||
|
||||
#define ELF_START_ADDR 0x08048000
|
||||
#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;
|
||||
@@ -90,15 +112,21 @@ void g(int c)
|
||||
ind = ind1;
|
||||
}
|
||||
|
||||
void o(int c)
|
||||
ST_FUNC void o(unsigned int c)
|
||||
{
|
||||
while (c) {
|
||||
g(c);
|
||||
c = c / 256;
|
||||
c = c >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -107,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) {
|
||||
@@ -118,7 +146,7 @@ void gsym_addr(int t, int a)
|
||||
}
|
||||
}
|
||||
|
||||
void gsym(int t)
|
||||
ST_FUNC void gsym(int t)
|
||||
{
|
||||
gsym_addr(t, ind);
|
||||
}
|
||||
@@ -128,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;
|
||||
|
||||
@@ -143,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)
|
||||
@@ -173,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;
|
||||
@@ -190,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 */
|
||||
@@ -219,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 */
|
||||
@@ -240,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;
|
||||
@@ -262,7 +313,7 @@ void store(int r, SValue *v)
|
||||
} else {
|
||||
if (bt == VT_SHORT)
|
||||
o(0x66);
|
||||
if (bt == VT_BYTE)
|
||||
if (bt == VT_BYTE || bt == VT_BOOL)
|
||||
o(0x88);
|
||||
else
|
||||
o(0x89);
|
||||
@@ -310,12 +361,15 @@ static void gcall_or_jmp(int is_jmp)
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX };
|
||||
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;
|
||||
int size, align, r, args_size, i, func_call;
|
||||
Sym *func_sym;
|
||||
|
||||
args_size = 0;
|
||||
@@ -367,34 +421,85 @@ void gfunc_call(int nb_args)
|
||||
}
|
||||
save_regs(0); /* save used temporary registers */
|
||||
func_sym = vtop->type.ref;
|
||||
func_call = FUNC_CALL(func_sym->r);
|
||||
/* fast call case */
|
||||
if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) ||
|
||||
func_call == FUNC_FASTCALLW) {
|
||||
int fastcall_nb_regs;
|
||||
uint8_t *fastcall_regs_ptr;
|
||||
if (func_call == FUNC_FASTCALLW) {
|
||||
fastcall_regs_ptr = fastcallw_regs;
|
||||
fastcall_nb_regs = 2;
|
||||
} else {
|
||||
fastcall_regs_ptr = fastcall_regs;
|
||||
fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
|
||||
}
|
||||
for(i = 0;i < fastcall_nb_regs; i++) {
|
||||
if (args_size <= 0)
|
||||
break;
|
||||
o(0x58 + fastcall_regs_ptr[i]); /* pop r */
|
||||
/* XXX: incorrect for struct/floats */
|
||||
args_size -= 4;
|
||||
}
|
||||
}
|
||||
gcall_or_jmp(0);
|
||||
if (args_size && func_sym->r == FUNC_CDECL)
|
||||
|
||||
#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--;
|
||||
}
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
#define FUNC_PROLOG_SIZE 10
|
||||
#else
|
||||
#define FUNC_PROLOG_SIZE 9
|
||||
#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;
|
||||
int addr, align, size, func_call, fastcall_nb_regs;
|
||||
int param_index, param_addr;
|
||||
uint8_t *fastcall_regs_ptr;
|
||||
Sym *sym;
|
||||
CType *type;
|
||||
|
||||
sym = func_type->ref;
|
||||
func_call = sym->r;
|
||||
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;
|
||||
} else if (func_call == FUNC_FASTCALLW) {
|
||||
fastcall_nb_regs = 2;
|
||||
fastcall_regs_ptr = fastcallw_regs;
|
||||
} else {
|
||||
fastcall_nb_regs = 0;
|
||||
fastcall_regs_ptr = NULL;
|
||||
}
|
||||
param_index = 0;
|
||||
|
||||
ind += FUNC_PROLOG_SIZE;
|
||||
func_sub_sp_offset = ind;
|
||||
/* if the function returns a structure, then add an
|
||||
implicit pointer parameter */
|
||||
func_vt = sym->type;
|
||||
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
|
||||
/* XXX: fastcall case ? */
|
||||
func_vc = addr;
|
||||
addr += 4;
|
||||
param_index++;
|
||||
}
|
||||
/* define parameters */
|
||||
while ((sym = sym->next) != NULL) {
|
||||
type = &sym->type;
|
||||
sym_push(sym->v & ~SYM_FIELD, type,
|
||||
VT_LOCAL | VT_LVAL, addr);
|
||||
size = type_size(type, &align);
|
||||
size = (size + 3) & ~3;
|
||||
#ifdef FUNC_STRUCT_PARAM_AS_PTR
|
||||
@@ -403,27 +508,47 @@ void gfunc_prolog(CType *func_type)
|
||||
size = 4;
|
||||
}
|
||||
#endif
|
||||
addr += size;
|
||||
if (param_index < fastcall_nb_regs) {
|
||||
/* save FASTCALL register */
|
||||
loc -= 4;
|
||||
o(0x89); /* movl */
|
||||
gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc);
|
||||
param_addr = loc;
|
||||
} else {
|
||||
param_addr = addr;
|
||||
addr += size;
|
||||
}
|
||||
sym_push(sym->v & ~SYM_FIELD, type,
|
||||
VT_LOCAL | lvalue_type(type->t), param_addr);
|
||||
param_index++;
|
||||
}
|
||||
func_ret_sub = 0;
|
||||
/* pascal type call ? */
|
||||
if (func_call == FUNC_STDCALL)
|
||||
func_ret_sub = addr - 8;
|
||||
o(0xe58955); /* push %ebp, mov %esp, %ebp */
|
||||
func_sub_sp_offset = oad(0xec81, 0); /* sub $xxx, %esp */
|
||||
#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 (do_bounds_check) {
|
||||
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;
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (do_bounds_check && func_bound_offset != lbounds_section->data_offset) {
|
||||
if (tcc_state->do_bounds_check
|
||||
&& func_bound_offset != lbounds_section->data_offset) {
|
||||
int saved_ind;
|
||||
int *bounds_ptr;
|
||||
Sym *sym, *sym_data;
|
||||
@@ -432,7 +557,7 @@ void gfunc_epilog(void)
|
||||
*bounds_ptr = 0;
|
||||
/* generate bound local allocation */
|
||||
saved_ind = ind;
|
||||
ind = func_sub_sp_offset + 4;
|
||||
ind = func_sub_sp_offset;
|
||||
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
||||
func_bound_offset, lbounds_section->data_offset);
|
||||
greloc(cur_text_section, sym_data,
|
||||
@@ -464,17 +589,37 @@ void gfunc_epilog(void)
|
||||
g(func_ret_sub >> 8);
|
||||
}
|
||||
/* align local size to word & save local variables */
|
||||
*(int *)(cur_text_section->data + func_sub_sp_offset) = (-loc + 3) & -4;
|
||||
|
||||
v = (-loc + 3) & -4;
|
||||
saved_ind = ind;
|
||||
ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (v >= 4096) {
|
||||
Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
|
||||
oad(0xb8, v); /* mov stacksize, %eax */
|
||||
oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
|
||||
greloc(cur_text_section, sym, ind-4, R_386_PC32);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
o(0xe58955); /* push %ebp, mov %esp, %ebp */
|
||||
o(0xec81); /* sub esp, stacksize */
|
||||
gen_le32(v);
|
||||
#if FUNC_PROLOG_SIZE == 10
|
||||
o(0x90); /* adjust to FUNC_PROLOG_SIZE */
|
||||
#endif
|
||||
}
|
||||
ind = saved_ind;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
@@ -487,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;
|
||||
|
||||
@@ -510,7 +655,8 @@ int gtst(int inv, int t)
|
||||
gsym(vtop->c.i);
|
||||
}
|
||||
} else {
|
||||
if (is_float(vtop->type.t)) {
|
||||
if (is_float(vtop->type.t) ||
|
||||
(vtop->type.t & VT_BTYPE) == VT_LLONG) {
|
||||
vpushi(0);
|
||||
gen_op(TOK_NE);
|
||||
}
|
||||
@@ -531,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;
|
||||
|
||||
@@ -547,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);
|
||||
@@ -665,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;
|
||||
|
||||
@@ -777,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);
|
||||
@@ -807,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)
|
||||
@@ -857,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--;
|
||||
@@ -874,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;
|
||||
|
||||
@@ -897,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;
|
||||
@@ -922,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;
|
||||
}
|
||||
@@ -939,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
|
||||
30
il-gen.c
30
il-gen.c
@@ -3,19 +3,19 @@
|
||||
*
|
||||
* Copyright (c) 2002 Fabrice Bellard
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 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 program 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 General Public License for more details.
|
||||
* 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 General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* number of available registers */
|
||||
@@ -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);
|
||||
@@ -449,7 +449,7 @@ void gfunc_prolog(int t)
|
||||
while ((sym = sym->next) != NULL) {
|
||||
u = sym->t;
|
||||
sym_push(sym->v & ~SYM_FIELD, u,
|
||||
VT_LOCAL | VT_LVAL, addr);
|
||||
VT_LOCAL | lvalue_type(sym->type.t), addr);
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
41
include/stdarg.h
Normal file
41
include/stdarg.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef _STDARG_H
|
||||
#define _STDARG_H
|
||||
|
||||
#ifdef __x86_64__
|
||||
#ifndef _WIN64
|
||||
|
||||
typedef void *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);
|
||||
|
||||
#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 */
|
||||
typedef va_list __gnuc_va_list;
|
||||
#define _VA_LIST_DEFINED
|
||||
|
||||
#endif /* _STDARG_H */
|
||||
28
include/stddef.h
Normal file
28
include/stddef.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef _STDDEF_H
|
||||
#define _STDDEF_H
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __PTRDIFF_TYPE__ ssize_t;
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||
typedef __PTRDIFF_TYPE__ intptr_t;
|
||||
typedef __SIZE_TYPE__ uintptr_t;
|
||||
|
||||
#ifndef __int8_t_defined
|
||||
#define __int8_t_defined
|
||||
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
|
||||
@@ -18,6 +18,7 @@ void *realloc(void *ptr, size_t size);
|
||||
int atoi(const char *nptr);
|
||||
long int strtol(const char *nptr, char **endptr, int base);
|
||||
unsigned long int strtoul(const char *nptr, char **endptr, int base);
|
||||
void exit(int);
|
||||
|
||||
/* stdio.h */
|
||||
typedef struct __FILE FILE;
|
||||
12
include/varargs.h
Normal file
12
include/varargs.h
Normal file
@@ -0,0 +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
|
||||
|
||||
#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
|
||||
47
lib/alloca86-bt.S
Normal file
47
lib/alloca86-bt.S
Normal file
@@ -0,0 +1,47 @@
|
||||
/* ---------------------------------------------- */
|
||||
/* alloca86-bt.S */
|
||||
|
||||
.globl __bound_alloca
|
||||
|
||||
__bound_alloca:
|
||||
pop %edx
|
||||
pop %eax
|
||||
mov %eax, %ecx
|
||||
add $3,%eax
|
||||
and $-4,%eax
|
||||
jz p6
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
p4:
|
||||
cmp $4096,%eax
|
||||
jle p5
|
||||
sub $4096,%esp
|
||||
sub $4096,%eax
|
||||
test %eax,(%esp)
|
||||
jmp p4
|
||||
|
||||
p5:
|
||||
#endif
|
||||
|
||||
sub %eax,%esp
|
||||
mov %esp,%eax
|
||||
|
||||
push %edx
|
||||
push %eax
|
||||
push %ecx
|
||||
push %eax
|
||||
call __bound_new_region
|
||||
add $8, %esp
|
||||
pop %eax
|
||||
pop %edx
|
||||
|
||||
p6:
|
||||
push %edx
|
||||
push %edx
|
||||
ret
|
||||
|
||||
/* mark stack as nonexecutable */
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
/* ---------------------------------------------- */
|
||||
35
lib/alloca86.S
Normal file
35
lib/alloca86.S
Normal file
@@ -0,0 +1,35 @@
|
||||
/* ---------------------------------------------- */
|
||||
/* alloca86.S */
|
||||
|
||||
.globl alloca
|
||||
|
||||
alloca:
|
||||
pop %edx
|
||||
pop %eax
|
||||
add $3,%eax
|
||||
and $-4,%eax
|
||||
jz p3
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
p1:
|
||||
cmp $4096,%eax
|
||||
jle p2
|
||||
sub $4096,%esp
|
||||
sub $4096,%eax
|
||||
test %eax,(%esp)
|
||||
jmp p1
|
||||
p2:
|
||||
#endif
|
||||
|
||||
sub %eax,%esp
|
||||
mov %esp,%eax
|
||||
p3:
|
||||
push %edx
|
||||
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
|
||||
/* ---------------------------------------------- */
|
||||
@@ -3,27 +3,31 @@
|
||||
*
|
||||
* Copyright (c) 2002 Fabrice Bellard
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 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 program 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 General Public License for more details.
|
||||
* 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 General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#ifndef __FreeBSD__
|
||||
#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,11 +37,13 @@
|
||||
|
||||
/* use malloc hooks. Currently the code cannot be reliable if no hooks */
|
||||
#define CONFIG_TCC_MALLOC_HOOKS
|
||||
|
||||
#define HAVE_MEMALIGN
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#warning Bound checking not fully supported on FreeBSD
|
||||
#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
|
||||
@@ -74,19 +80,7 @@ void __bound_init(void);
|
||||
void __bound_new_region(void *p, unsigned long size);
|
||||
int __bound_delete_region(void *p);
|
||||
|
||||
/* currently, tcc cannot compile that because we use unsupported GNU C
|
||||
extensions */
|
||||
#if !defined(__TINYC__)
|
||||
void *__bound_ptr_add(void *p, int offset) __attribute__((regparm(2)));
|
||||
void *__bound_ptr_indir1(void *p, int offset) __attribute__((regparm(2)));
|
||||
void *__bound_ptr_indir2(void *p, int offset) __attribute__((regparm(2)));
|
||||
void *__bound_ptr_indir4(void *p, int offset) __attribute__((regparm(2)));
|
||||
void *__bound_ptr_indir8(void *p, int offset) __attribute__((regparm(2)));
|
||||
void *__bound_ptr_indir12(void *p, int offset) __attribute__((regparm(2)));
|
||||
void *__bound_ptr_indir16(void *p, int offset) __attribute__((regparm(2)));
|
||||
void __bound_local_new(void *p) __attribute__((regparm(1)));
|
||||
void __bound_local_delete(void *p) __attribute__((regparm(1)));
|
||||
#endif
|
||||
#define FASTCALL __attribute__((regparm(3)))
|
||||
|
||||
void *__bound_malloc(size_t size, const void *caller);
|
||||
void *__bound_memalign(size_t size, size_t align, const void *caller);
|
||||
@@ -104,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 */
|
||||
@@ -163,12 +154,9 @@ 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 *__bound_ptr_add(void *p, int offset)
|
||||
void * FASTCALL __bound_ptr_add(void *p, int offset)
|
||||
{
|
||||
unsigned long addr = (unsigned long)p;
|
||||
BoundEntry *e;
|
||||
@@ -194,7 +182,7 @@ void *__bound_ptr_add(void *p, int offset)
|
||||
/* return '(p + offset)' for pointer indirection (the resulting must
|
||||
be strictly inside the region */
|
||||
#define BOUND_PTR_INDIR(dsize) \
|
||||
void *__bound_ptr_indir ## dsize (void *p, int offset) \
|
||||
void * FASTCALL __bound_ptr_indir ## dsize (void *p, int offset) \
|
||||
{ \
|
||||
unsigned long addr = (unsigned long)p; \
|
||||
BoundEntry *e; \
|
||||
@@ -214,20 +202,21 @@ void *__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 __bound_local_new(void *p1)
|
||||
void FASTCALL __bound_local_new(void *p1)
|
||||
{
|
||||
unsigned long addr, size, fp, *p = p1;
|
||||
GET_CALLER_FP(fp);
|
||||
@@ -243,7 +232,7 @@ void __bound_local_new(void *p1)
|
||||
}
|
||||
|
||||
/* called when leaving a function to delete all the local regions */
|
||||
void __bound_local_delete(void *p1)
|
||||
void FASTCALL __bound_local_delete(void *p1)
|
||||
{
|
||||
unsigned long addr, fp, *p = p1;
|
||||
GET_CALLER_FP(fp);
|
||||
@@ -257,34 +246,6 @@ void __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;
|
||||
@@ -417,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
|
||||
@@ -434,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)
|
||||
{
|
||||
@@ -627,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;
|
||||
@@ -659,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
|
||||
@@ -670,6 +662,8 @@ static void install_malloc_hooks(void)
|
||||
__free_hook = __bound_free;
|
||||
__realloc_hook = __bound_realloc;
|
||||
__memalign_hook = __bound_memalign;
|
||||
|
||||
barrier();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -680,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
|
||||
}
|
||||
|
||||
@@ -782,7 +778,7 @@ void *__bound_calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
size = size * nmemb;
|
||||
ptr = __bound_malloc(size);
|
||||
ptr = __bound_malloc(size, NULL);
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
memset(ptr, 0, size);
|
||||
@@ -89,13 +89,13 @@ union double_long {
|
||||
double d;
|
||||
#if 1
|
||||
struct {
|
||||
unsigned long lower;
|
||||
long upper;
|
||||
unsigned int lower;
|
||||
int upper;
|
||||
} l;
|
||||
#else
|
||||
struct {
|
||||
long upper;
|
||||
unsigned long lower;
|
||||
int upper;
|
||||
unsigned int lower;
|
||||
} l;
|
||||
#endif
|
||||
long long ll;
|
||||
@@ -106,6 +106,9 @@ union float_long {
|
||||
long l;
|
||||
};
|
||||
|
||||
/* XXX: we don't support several builtin supports for now */
|
||||
#ifndef __x86_64__
|
||||
|
||||
/* XXX: use gcc/tcc intrinsic ? */
|
||||
#if defined(__i386__)
|
||||
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
||||
@@ -159,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)
|
||||
@@ -399,7 +402,7 @@ long long __moddi3(long long u, long long v)
|
||||
if (vv.s.high < 0)
|
||||
vv.ll = __negdi2 (vv.ll);
|
||||
|
||||
__udivmoddi4 (uu.ll, vv.ll, &w);
|
||||
__udivmoddi4 (uu.ll, vv.ll, (UDWtype *) &w);
|
||||
if (c)
|
||||
w = __negdi2 (w);
|
||||
return w;
|
||||
@@ -419,7 +422,7 @@ unsigned long long __umoddi3(unsigned long long u, unsigned long long v)
|
||||
}
|
||||
|
||||
/* XXX: fix tcc's code generator to do this instead */
|
||||
long long __sardi3(long long a, int b)
|
||||
long long __ashrdi3(long long a, int b)
|
||||
{
|
||||
#ifdef __TINYC__
|
||||
DWunion u;
|
||||
@@ -438,7 +441,7 @@ long long __sardi3(long long a, int b)
|
||||
}
|
||||
|
||||
/* XXX: fix tcc's code generator to do this instead */
|
||||
unsigned long long __shrdi3(unsigned long long a, int b)
|
||||
unsigned long long __lshrdi3(unsigned long long a, int b)
|
||||
{
|
||||
#ifdef __TINYC__
|
||||
DWunion u;
|
||||
@@ -457,7 +460,7 @@ unsigned long long __shrdi3(unsigned long long a, int b)
|
||||
}
|
||||
|
||||
/* XXX: fix tcc's code generator to do this instead */
|
||||
long long __shldi3(long long a, int b)
|
||||
long long __ashldi3(long long a, int b)
|
||||
{
|
||||
#ifdef __TINYC__
|
||||
DWunion u;
|
||||
@@ -466,7 +469,7 @@ long long __shldi3(long long a, int b)
|
||||
u.s.high = (unsigned)u.s.low << (b - 32);
|
||||
u.s.low = 0;
|
||||
} else if (b != 0) {
|
||||
u.s.high = ((unsigned)u.s.high << b) | (u.s.low >> (32 - b));
|
||||
u.s.high = ((unsigned)u.s.high << b) | ((unsigned)u.s.low >> (32 - b));
|
||||
u.s.low = (unsigned)u.s.low << b;
|
||||
}
|
||||
return u.ll;
|
||||
@@ -482,8 +485,10 @@ unsigned short __tcc_fpu_control = 0x137f;
|
||||
unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00;
|
||||
#endif
|
||||
|
||||
#endif /* !__x86_64__ */
|
||||
|
||||
/* XXX: fix tcc's code generator to do this instead */
|
||||
float __ulltof(unsigned long long a)
|
||||
float __floatundisf(unsigned long long a)
|
||||
{
|
||||
DWunion uu;
|
||||
XFtype r;
|
||||
@@ -498,7 +503,7 @@ float __ulltof(unsigned long long a)
|
||||
}
|
||||
}
|
||||
|
||||
double __ulltod(unsigned long long a)
|
||||
double __floatundidf(unsigned long long a)
|
||||
{
|
||||
DWunion uu;
|
||||
XFtype r;
|
||||
@@ -513,7 +518,7 @@ double __ulltod(unsigned long long a)
|
||||
}
|
||||
}
|
||||
|
||||
long double __ulltold(unsigned long long a)
|
||||
long double __floatundixf(unsigned long long a)
|
||||
{
|
||||
DWunion uu;
|
||||
XFtype r;
|
||||
@@ -600,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__ */
|
||||
69
libtcc.h
69
libtcc.h
@@ -1,6 +1,10 @@
|
||||
#ifndef LIBTCC_H
|
||||
#define LIBTCC_H
|
||||
|
||||
#ifndef LIBTCCAPI
|
||||
# define LIBTCCAPI
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -10,81 +14,84 @@ struct TCCState;
|
||||
typedef struct TCCState TCCState;
|
||||
|
||||
/* create a new TCC compilation context */
|
||||
TCCState *tcc_new(void);
|
||||
LIBTCCAPI TCCState *tcc_new(void);
|
||||
|
||||
/* free a TCC compilation context */
|
||||
void tcc_delete(TCCState *s);
|
||||
LIBTCCAPI void tcc_delete(TCCState *s);
|
||||
|
||||
/* add debug information in the generated code */
|
||||
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 */
|
||||
void tcc_set_error_func(TCCState *s, void *error_opaque,
|
||||
void (*error_func)(void *opaque, const char *msg));
|
||||
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque,
|
||||
void (*error_func)(void *opaque, const char *msg));
|
||||
|
||||
/* set/reset a warning */
|
||||
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 */
|
||||
|
||||
/* add include path */
|
||||
int tcc_add_include_path(TCCState *s, const char *pathname);
|
||||
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname);
|
||||
|
||||
/* add in system include path */
|
||||
int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
|
||||
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
|
||||
|
||||
/* define preprocessor symbol 'sym'. Can put optional value */
|
||||
void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
|
||||
LIBTCCAPI void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
|
||||
|
||||
/* undefine preprocess symbol 'sym' */
|
||||
void tcc_undefine_symbol(TCCState *s, const char *sym);
|
||||
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. */
|
||||
int tcc_add_file(TCCState *s, const char *filename);
|
||||
/* 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. */
|
||||
int tcc_compile_string(TCCState *s, const char *buf);
|
||||
/* 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 */
|
||||
int tcc_set_output_type(TCCState *s, int output_type);
|
||||
#define TCC_OUTPUT_PREPROCESS 4 /* only preprocess (used internally) */
|
||||
|
||||
/* equivalent to -Lpath option */
|
||||
int tcc_add_library_path(TCCState *s, const char *pathname);
|
||||
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
|
||||
|
||||
/* the library name is the same as the argument of the '-l' option */
|
||||
int tcc_add_library(TCCState *s, const char *libraryname);
|
||||
LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname);
|
||||
|
||||
/* add a symbol to the compiled program */
|
||||
int tcc_add_symbol(TCCState *s, const char *name, unsigned long 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. */
|
||||
int tcc_output_file(TCCState *s, const char *filename);
|
||||
LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
|
||||
|
||||
/* link and run main() function and return its value. DO NOT call
|
||||
tcc_relocate() before. */
|
||||
int tcc_run(TCCState *s, int argc, char **argv);
|
||||
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
|
||||
|
||||
/* do all relocations (needed before using tcc_get_symbol()). Return
|
||||
non zero if link error. */
|
||||
int tcc_relocate(TCCState *s);
|
||||
/* 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. return 0 if OK, -1 if symbol not found */
|
||||
int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name);
|
||||
/* return symbol value or NULL if not found */
|
||||
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
15
stdarg.h
15
stdarg.h
@@ -1,15 +0,0 @@
|
||||
#ifndef _STDARG_H
|
||||
#define _STDARG_H
|
||||
|
||||
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_end(ap)
|
||||
|
||||
/* fix a buggy dependency on GCC in libio.h */
|
||||
typedef va_list __gnuc_va_list;
|
||||
#define _VA_LIST_DEFINED
|
||||
|
||||
#endif
|
||||
21
stddef.h
21
stddef.h
@@ -1,21 +0,0 @@
|
||||
#ifndef _STDDEF_H
|
||||
#define _STDDEF_H
|
||||
|
||||
#define NULL ((void *)0)
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||
#define offsetof(type, field) ((size_t) &((type *)0)->field)
|
||||
|
||||
/* need to do that because of glibc 2.1 bug (should have a way to test
|
||||
presence of 'long long' without __GNUC__, or TCC should define
|
||||
__GNUC__ ? */
|
||||
#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;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
272
tcc-doc.texi
272
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
|
||||
@@ -16,11 +20,8 @@
|
||||
@headings double
|
||||
@end iftex
|
||||
|
||||
@c @ifhtml
|
||||
@contents
|
||||
@c @end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
@node Top, Introduction, (dir), (dir)
|
||||
@top Tiny C Compiler Reference Documentation
|
||||
|
||||
@@ -29,10 +30,14 @@ This manual documents version @value{VERSION} of the Tiny C Compiler.
|
||||
@menu
|
||||
* Introduction:: Introduction to tcc.
|
||||
* Invoke:: Invocation of tcc (command line, options).
|
||||
* Clang:: ANSI C and extensions.
|
||||
* asm:: Assembler syntax.
|
||||
* linker:: Output file generation and supported targets.
|
||||
* Bounds:: Automatic bounds-checking of C code.
|
||||
* Libtcc:: The libtcc library.
|
||||
* devel:: Guide for Developers.
|
||||
@end menu
|
||||
@end ifnothtml
|
||||
|
||||
|
||||
@node Introduction
|
||||
@chapter Introduction
|
||||
@@ -42,7 +47,7 @@ compilers, it is meant to be self-relying: you do not need an
|
||||
external assembler or linker because TCC does that for you.
|
||||
|
||||
TCC compiles so @emph{fast} that even for big projects @code{Makefile}s may
|
||||
not be necessary.
|
||||
not be necessary.
|
||||
|
||||
TCC not only supports ANSI C, but also most of the new ISO C99
|
||||
standard and many GNUC extensions including inline assembly.
|
||||
@@ -58,11 +63,16 @@ these checks even if non patched libraries are used.
|
||||
With @code{libtcc}, you can use TCC as a backend for dynamic code
|
||||
generation (@pxref{Libtcc}).
|
||||
|
||||
TCC mainly supports the i386 target on Linux and Windows. There are alpha
|
||||
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 @url{tcc-win32.txt}.
|
||||
|
||||
@node Invoke
|
||||
@chapter Command line invocation
|
||||
|
||||
[This manual documents version @value{VERSION} of the Tiny C Compiler]
|
||||
|
||||
@section Quick start
|
||||
|
||||
@example
|
||||
@@ -89,9 +99,11 @@ the @code{main()} of a.c.
|
||||
|
||||
@item @samp{tcc a.c -run b.c arg1}
|
||||
Compile @file{a.c} and @file{b.c}, link them together and execute them. arg1 is given
|
||||
as first argument to the @code{main()} of the resulting program. Because
|
||||
multiple C files are specified, @option{--} are necessary to clearly separate the
|
||||
program arguments from the TCC options.
|
||||
as first argument to the @code{main()} of the resulting program.
|
||||
@ignore
|
||||
Because multiple C files are specified, @option{--} are necessary to clearly
|
||||
separate the program arguments from the TCC options.
|
||||
@end ignore
|
||||
|
||||
@item @samp{tcc -o myprog a.c b.c}
|
||||
Compile @file{a.c} and @file{b.c}, link them and generate the executable @file{myprog}.
|
||||
@@ -130,6 +142,13 @@ int main()
|
||||
return 0;
|
||||
@}
|
||||
@end example
|
||||
|
||||
TCC can read C source code from @emph{standard input} when @option{-} is used in
|
||||
place of @option{infile}. Example:
|
||||
|
||||
@example
|
||||
echo 'main()@{puts("hello");@}' | tcc -run -
|
||||
@end example
|
||||
@c man end
|
||||
|
||||
@section Option summary
|
||||
@@ -138,44 +157,41 @@ General Options:
|
||||
|
||||
@c man begin OPTIONS
|
||||
@table @option
|
||||
@item -v
|
||||
Display current TCC version.
|
||||
|
||||
@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:
|
||||
@@ -199,6 +215,26 @@ also be defined: @option{-DF(a)=a+1}
|
||||
Undefine preprocessor symbol @samp{sym}.
|
||||
@end table
|
||||
|
||||
Compilation flags:
|
||||
|
||||
Note: each of the following warning options has a negative form beginning with
|
||||
@option{-fno-}.
|
||||
|
||||
@table @option
|
||||
@item -funsigned-char
|
||||
Let the @code{char} type be unsigned.
|
||||
|
||||
@item -fsigned-char
|
||||
Let the @code{char} type be signed.
|
||||
|
||||
@item -fno-common
|
||||
Do not generate common symbols for uninitialized data.
|
||||
|
||||
@item -fleading-underscore
|
||||
Add a leading underscore at the beginning of each C symbol.
|
||||
|
||||
@end table
|
||||
|
||||
Warning options:
|
||||
|
||||
@table @option
|
||||
@@ -211,11 +247,14 @@ Note: each of the following warning options has a negative form beginning with
|
||||
@option{-Wno-}.
|
||||
|
||||
@table @option
|
||||
@item -Wimplicit-function-declaration
|
||||
Warn about implicit function declaration.
|
||||
|
||||
@item -Wunsupported
|
||||
Warn about unsupported GCC features that are ignored by TCC.
|
||||
|
||||
@item -Wwrite-strings
|
||||
Make string constants being of type @code{const char *} intead of @code{char
|
||||
Make string constants be of type @code{const char *} instead of @code{char
|
||||
*}.
|
||||
|
||||
@item -Werror
|
||||
@@ -223,7 +262,7 @@ Abort compilation if warnings are issued.
|
||||
|
||||
@item -Wall
|
||||
Activate all warnings, except @option{-Werror}, @option{-Wunusupported} and
|
||||
@option{-Wwrite-strings} (currently not useful).
|
||||
@option{-Wwrite-strings}.
|
||||
|
||||
@end table
|
||||
|
||||
@@ -239,21 +278,49 @@ 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,-rpath=path
|
||||
Put custom seatch path for dynamic libraries into executable.
|
||||
|
||||
@item -Wl,--oformat=fmt
|
||||
Use @var{fmt} as output format. The supported output formats are:
|
||||
@table @code
|
||||
@item elf32-i386
|
||||
ELF output format (default)
|
||||
@item binary
|
||||
Binary image (only for executable output)
|
||||
@item coff
|
||||
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
|
||||
|
||||
@@ -271,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
|
||||
@@ -296,6 +376,7 @@ Fabrice Bellard
|
||||
|
||||
@end ignore
|
||||
|
||||
@node Clang
|
||||
@chapter C language support
|
||||
|
||||
@section ANSI C
|
||||
@@ -397,21 +478,41 @@ instead of
|
||||
@}
|
||||
@end example
|
||||
|
||||
@cindex aligned attribute
|
||||
@cindex packed attribute
|
||||
@cindex section attribute
|
||||
@cindex unused attribute
|
||||
@cindex cdecl attribute
|
||||
@cindex stdcall attribute
|
||||
@cindex regparm attribute
|
||||
@cindex dllexport attribute
|
||||
|
||||
@item The keyword @code{__attribute__} is handled to specify variable or
|
||||
function attributes. The following attributes are supported:
|
||||
@itemize
|
||||
@item @code{aligned(n)}: align data to n bytes (must be a power of two).
|
||||
|
||||
@item @code{section(name)}: generate function or data in assembly
|
||||
section name (name is a string containing the section name) instead
|
||||
of the default section.
|
||||
@item @code{aligned(n)}: align a variable or a structure field to n bytes
|
||||
(must be a power of two).
|
||||
|
||||
@item @code{packed}: force alignment of a variable or a structure field to
|
||||
1.
|
||||
|
||||
@item @code{section(name)}: generate function or data in assembly section
|
||||
name (name is a string containing the section name) instead of the default
|
||||
section.
|
||||
|
||||
@item @code{unused}: specify that the variable or the function is unused.
|
||||
|
||||
@item @code{cdecl}: use standard C calling convention.
|
||||
@item @code{cdecl}: use standard C calling convention (default).
|
||||
|
||||
@item @code{stdcall}: use Pascal-like calling convention.
|
||||
|
||||
@item @code{regparm(n)}: use fast i386 calling convention. @var{n} must be
|
||||
between 1 and 3. The first @var{n} function parameters are respectively put in
|
||||
registers @code{%eax}, @code{%edx} and @code{%ecx}.
|
||||
|
||||
@item @code{dllexport}: export function from dll/executable (win32 only)
|
||||
|
||||
@end itemize
|
||||
|
||||
Here are some examples:
|
||||
@@ -487,6 +588,8 @@ operands are supported.
|
||||
@item @code{__builtin_types_compatible_p()} and @code{__builtin_constant_p()}
|
||||
are supported.
|
||||
|
||||
@item @code{#pragma pack} is supported for win32 compatibility.
|
||||
|
||||
@end itemize
|
||||
|
||||
@section TinyCC extensions
|
||||
@@ -505,6 +608,7 @@ indicate that you use TCC.
|
||||
|
||||
@end itemize
|
||||
|
||||
@node asm
|
||||
@chapter TinyCC Assembler
|
||||
|
||||
Since version 0.9.16, TinyCC integrates its own assembler. TinyCC
|
||||
@@ -576,20 +680,27 @@ They can be defined several times in the same source. Use 'b'
|
||||
@section Directives
|
||||
@cindex assembler directives
|
||||
@cindex directives, assembler
|
||||
@cindex .align
|
||||
@cindex .skip
|
||||
@cindex .space
|
||||
@cindex .byte
|
||||
@cindex .word
|
||||
@cindex .short
|
||||
@cindex .int
|
||||
@cindex .long
|
||||
@cindex .string
|
||||
@cindex .globl
|
||||
@cindex .section
|
||||
@cindex .text
|
||||
@cindex .data
|
||||
@cindex .bss
|
||||
@cindex align directive
|
||||
@cindex skip directive
|
||||
@cindex space directive
|
||||
@cindex byte directive
|
||||
@cindex word directive
|
||||
@cindex short directive
|
||||
@cindex int directive
|
||||
@cindex long directive
|
||||
@cindex quad directive
|
||||
@cindex globl directive
|
||||
@cindex global directive
|
||||
@cindex section directive
|
||||
@cindex text directive
|
||||
@cindex data directive
|
||||
@cindex bss directive
|
||||
@cindex fill directive
|
||||
@cindex org directive
|
||||
@cindex previous directive
|
||||
@cindex string directive
|
||||
@cindex asciz directive
|
||||
@cindex ascii directive
|
||||
|
||||
All directives are preceeded by a '.'. The following directives are
|
||||
supported:
|
||||
@@ -598,17 +709,24 @@ supported:
|
||||
@item .align n[,value]
|
||||
@item .skip n[,value]
|
||||
@item .space n[,value]
|
||||
@item .byte value1[,value2...]
|
||||
@item .word value1[,value2...]
|
||||
@item .short value1[,value2...]
|
||||
@item .int value1[,value2...]
|
||||
@item .long value1[,value2...]
|
||||
@item .string string
|
||||
@item .byte value1[,...]
|
||||
@item .word value1[,...]
|
||||
@item .short value1[,...]
|
||||
@item .int value1[,...]
|
||||
@item .long value1[,...]
|
||||
@item .quad immediate_value1[,...]
|
||||
@item .globl symbol
|
||||
@item .global symbol
|
||||
@item .section section
|
||||
@item .text
|
||||
@item .data
|
||||
@item .bss
|
||||
@item .fill repeat[,size[,value]]
|
||||
@item .org n
|
||||
@item .previous
|
||||
@item .string string[,...]
|
||||
@item .asciz string[,...]
|
||||
@item .ascii string[,...]
|
||||
@end itemize
|
||||
|
||||
@section X86 Assembler
|
||||
@@ -620,6 +738,7 @@ tries to guess it from the operand sizes.
|
||||
|
||||
Currently, MMX opcodes are supported but not SSE ones.
|
||||
|
||||
@node linker
|
||||
@chapter TinyCC Linker
|
||||
@cindex linker
|
||||
|
||||
@@ -644,6 +763,14 @@ options (@option{--start-group} and @option{--end-group}) are supported.
|
||||
TCC can load ELF object files, archives (.a files) and dynamic
|
||||
libraries (.so).
|
||||
|
||||
@section PE-i386 file generation
|
||||
@cindex PE-i386
|
||||
|
||||
TCC for Windows supports the native Win32 executable file format (PE-i386). It
|
||||
generates EXE files (console and gui) and DLL files.
|
||||
|
||||
For usage on Windows, see also tcc-win32.txt.
|
||||
|
||||
@section GNU Linker Scripts
|
||||
@cindex scripts, linker
|
||||
@cindex linker scripts
|
||||
@@ -753,6 +880,7 @@ The idea consists in giving a C string containing the program you want
|
||||
to compile directly to @code{libtcc}. Then you can access to any global
|
||||
symbol (function or variable) defined.
|
||||
|
||||
@node devel
|
||||
@chapter Developer's guide
|
||||
|
||||
This chapter gives some hints to understand how TCC works. You can skip
|
||||
@@ -816,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
|
||||
@@ -829,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
|
||||
@@ -845,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
|
||||
@@ -856,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:
|
||||
|
||||
|
||||
491
tccasm.c
491
tccasm.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* GAS like assembler for TCC
|
||||
*
|
||||
* Copyright (c) 2001, 2002 Fabrice Bellard
|
||||
* 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
|
||||
@@ -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,6 +31,8 @@ static int asm_get_local_label_name(TCCState *s1, unsigned int n)
|
||||
return ts->tok;
|
||||
}
|
||||
|
||||
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. */
|
||||
|
||||
@@ -50,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) {
|
||||
@@ -65,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;
|
||||
@@ -79,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
|
||||
@@ -91,6 +96,11 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
||||
pe->sym = NULL;
|
||||
next();
|
||||
break;
|
||||
case '(':
|
||||
next();
|
||||
asm_expr(s1, pe);
|
||||
skip(')');
|
||||
break;
|
||||
default:
|
||||
if (tok >= TOK_IDENT) {
|
||||
/* label case : if the label was not found, add one */
|
||||
@@ -100,11 +110,17 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
||||
/* NOTE: by default, the symbol is global */
|
||||
sym->type.t = VT_VOID;
|
||||
}
|
||||
pe->v = 0;
|
||||
pe->sym = sym;
|
||||
if (sym->r == SHN_ABS) {
|
||||
/* if absolute symbol, no need to put a symbol value */
|
||||
pe->v = sym->jnext;
|
||||
pe->sym = NULL;
|
||||
} else {
|
||||
pe->v = 0;
|
||||
pe->sym = sym;
|
||||
}
|
||||
next();
|
||||
} else {
|
||||
error("bad expression syntax [%s]", get_tok_str(tok, &tokc));
|
||||
tcc_error("bad expression syntax [%s]", get_tok_str(tok, &tokc));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -124,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;
|
||||
@@ -132,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;
|
||||
@@ -165,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;
|
||||
@@ -212,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);
|
||||
@@ -241,7 +257,8 @@ static int asm_int_expr(TCCState *s1)
|
||||
|
||||
/* NOTE: the same name space as C labels is used to avoid using too
|
||||
much memory when storing labels in TokenStrings */
|
||||
static void asm_new_label(TCCState *s1, int label, int is_local)
|
||||
static void asm_new_label1(TCCState *s1, int label, int is_local,
|
||||
int sh_num, int value)
|
||||
{
|
||||
Sym *sym;
|
||||
|
||||
@@ -250,7 +267,7 @@ static void asm_new_label(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 */
|
||||
@@ -262,33 +279,49 @@ static void asm_new_label(TCCState *s1, int label, int is_local)
|
||||
sym = label_push(&s1->asm_labels, label, 0);
|
||||
sym->type.t = VT_STATIC | VT_VOID;
|
||||
}
|
||||
sym->r = cur_text_section->sh_num;
|
||||
sym->next = (void *)ind;
|
||||
sym->r = sh_num;
|
||||
sym->jnext = value;
|
||||
}
|
||||
|
||||
static void asm_new_label(TCCState *s1, int label, int is_local)
|
||||
{
|
||||
asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind);
|
||||
}
|
||||
|
||||
static void asm_free_labels(TCCState *st)
|
||||
{
|
||||
Sym *s, *s1;
|
||||
Section *sec;
|
||||
|
||||
for(s = st->asm_labels; s != NULL; s = s1) {
|
||||
s1 = s->prev;
|
||||
/* define symbol value in object file */
|
||||
if (s->r) {
|
||||
put_extern_sym(s, st->sections[s->r], (long)s->next, 0);
|
||||
if (s->r == SHN_ABS)
|
||||
sec = SECTION_ABS;
|
||||
else
|
||||
sec = st->sections[s->r];
|
||||
put_extern_sym2(s, sec, s->jnext, 0, 0);
|
||||
}
|
||||
/* remove label */
|
||||
table_ident[s->v - TOK_IDENT]->sym_label = NULL;
|
||||
tcc_free(s);
|
||||
sym_free(s);
|
||||
}
|
||||
st->asm_labels = NULL;
|
||||
}
|
||||
|
||||
static void use_section1(TCCState *s1, Section *sec)
|
||||
{
|
||||
cur_text_section->data_offset = ind;
|
||||
cur_text_section = sec;
|
||||
ind = cur_text_section->data_offset;
|
||||
}
|
||||
|
||||
static void use_section(TCCState *s1, const char *name)
|
||||
{
|
||||
Section *sec;
|
||||
sec = find_section(s1, name);
|
||||
cur_text_section->data_offset = ind;
|
||||
cur_text_section = sec;
|
||||
ind = cur_text_section->data_offset;
|
||||
use_section1(s1, sec);
|
||||
}
|
||||
|
||||
static void asm_parse_directive(TCCState *s1)
|
||||
@@ -309,9 +342,12 @@ 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 */
|
||||
if (sec->sh_addralign < n)
|
||||
sec->sh_addralign = n;
|
||||
} else {
|
||||
size = n;
|
||||
}
|
||||
@@ -320,6 +356,7 @@ static void asm_parse_directive(TCCState *s1)
|
||||
next();
|
||||
v = asm_int_expr(s1);
|
||||
}
|
||||
zero_pad:
|
||||
if (sec->sh_type != SHT_NOBITS) {
|
||||
sec->data_offset = ind;
|
||||
ptr = section_ptr_add(sec, size);
|
||||
@@ -327,6 +364,33 @@ static void asm_parse_directive(TCCState *s1)
|
||||
}
|
||||
ind += size;
|
||||
break;
|
||||
case TOK_ASM_quad:
|
||||
next();
|
||||
for(;;) {
|
||||
uint64_t vl;
|
||||
const char *p;
|
||||
|
||||
p = tokc.cstr->data;
|
||||
if (tok != TOK_PPNUM) {
|
||||
error_constant:
|
||||
tcc_error("64 bit constant");
|
||||
}
|
||||
vl = strtoll(p, (char **)&p, 0);
|
||||
if (*p != '\0')
|
||||
goto error_constant;
|
||||
next();
|
||||
if (sec->sh_type != SHT_NOBITS) {
|
||||
/* XXX: endianness */
|
||||
gen_le32(vl);
|
||||
gen_le32(vl >> 32);
|
||||
} else {
|
||||
ind += 8;
|
||||
}
|
||||
if (tok != ',')
|
||||
break;
|
||||
next();
|
||||
}
|
||||
break;
|
||||
case TOK_ASM_byte:
|
||||
size = 1;
|
||||
goto asm_data;
|
||||
@@ -361,8 +425,66 @@ static void asm_parse_directive(TCCState *s1)
|
||||
next();
|
||||
}
|
||||
break;
|
||||
case TOK_ASM_fill:
|
||||
{
|
||||
int repeat, size, val, i, j;
|
||||
uint8_t repeat_buf[8];
|
||||
next();
|
||||
repeat = asm_int_expr(s1);
|
||||
if (repeat < 0) {
|
||||
tcc_error("repeat < 0; .fill ignored");
|
||||
break;
|
||||
}
|
||||
size = 1;
|
||||
val = 0;
|
||||
if (tok == ',') {
|
||||
next();
|
||||
size = asm_int_expr(s1);
|
||||
if (size < 0) {
|
||||
tcc_error("size < 0; .fill ignored");
|
||||
break;
|
||||
}
|
||||
if (size > 8)
|
||||
size = 8;
|
||||
if (tok == ',') {
|
||||
next();
|
||||
val = asm_int_expr(s1);
|
||||
}
|
||||
}
|
||||
/* XXX: endianness */
|
||||
repeat_buf[0] = val;
|
||||
repeat_buf[1] = val >> 8;
|
||||
repeat_buf[2] = val >> 16;
|
||||
repeat_buf[3] = val >> 24;
|
||||
repeat_buf[4] = 0;
|
||||
repeat_buf[5] = 0;
|
||||
repeat_buf[6] = 0;
|
||||
repeat_buf[7] = 0;
|
||||
for(i = 0; i < repeat; i++) {
|
||||
for(j = 0; j < size; j++) {
|
||||
g(repeat_buf[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TOK_ASM_org:
|
||||
{
|
||||
unsigned long n;
|
||||
next();
|
||||
/* XXX: handle section symbols too */
|
||||
n = asm_int_expr(s1);
|
||||
if (n < ind)
|
||||
tcc_error("attempt to .org backwards");
|
||||
v = 0;
|
||||
size = n - ind;
|
||||
goto zero_pad;
|
||||
}
|
||||
break;
|
||||
case TOK_ASM_globl:
|
||||
{
|
||||
case TOK_ASM_global:
|
||||
case TOK_ASM_weak:
|
||||
tok1 = tok;
|
||||
do {
|
||||
Sym *sym;
|
||||
|
||||
next();
|
||||
@@ -372,21 +494,36 @@ 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:
|
||||
case TOK_ASM_asciz:
|
||||
{
|
||||
const uint8_t *p;
|
||||
int i;
|
||||
int i, size, t;
|
||||
|
||||
t = tok;
|
||||
next();
|
||||
if (tok != TOK_STR)
|
||||
expect("string constant");
|
||||
p = tokc.cstr->data;
|
||||
for(i = 0; i < tokc.cstr->size; i++)
|
||||
g(p[i]);
|
||||
next();
|
||||
for(;;) {
|
||||
if (tok != TOK_STR)
|
||||
expect("string constant");
|
||||
p = tokc.cstr->data;
|
||||
size = tokc.cstr->size;
|
||||
if (t == TOK_ASM_ascii && size > 0)
|
||||
size--;
|
||||
for(i = 0; i < size; i++)
|
||||
g(p[i]);
|
||||
next();
|
||||
if (tok == ',') {
|
||||
next();
|
||||
} else if (tok != TOK_STR) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TOK_ASM_text:
|
||||
@@ -405,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];
|
||||
@@ -419,11 +645,50 @@ static void asm_parse_directive(TCCState *s1)
|
||||
pstrcat(sname, sizeof(sname), get_tok_str(tok, NULL));
|
||||
next();
|
||||
}
|
||||
if (tok == ',') {
|
||||
/* skip section options */
|
||||
next();
|
||||
if (tok != TOK_STR)
|
||||
expect("string constant");
|
||||
next();
|
||||
}
|
||||
last_text_section = cur_text_section;
|
||||
use_section(s1, sname);
|
||||
}
|
||||
break;
|
||||
case TOK_ASM_previous:
|
||||
{
|
||||
Section *sec;
|
||||
next();
|
||||
if (!last_text_section)
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -470,7 +735,7 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
|
||||
|
||||
ch = file->buf_ptr[0];
|
||||
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
||||
parse_flags = 0;
|
||||
parse_flags = PARSE_FLAG_ASM_COMMENTS;
|
||||
if (do_preprocess)
|
||||
parse_flags |= PARSE_FLAG_PREPROCESS;
|
||||
next();
|
||||
@@ -506,6 +771,12 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
|
||||
asm_new_label(s1, opcode, 0);
|
||||
next();
|
||||
goto redo;
|
||||
} else if (tok == '=') {
|
||||
int n;
|
||||
next();
|
||||
n = asm_int_expr(s1);
|
||||
asm_new_label1(s1, opcode, 0, SHN_ABS, n);
|
||||
goto redo;
|
||||
} else {
|
||||
asm_opcode(s1, opcode);
|
||||
}
|
||||
@@ -524,8 +795,9 @@ 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;
|
||||
|
||||
preprocess_init(s1);
|
||||
@@ -534,9 +806,20 @@ static int tcc_assemble(TCCState *s1, int do_preprocess)
|
||||
cur_text_section = text_section;
|
||||
ind = cur_text_section->data_offset;
|
||||
|
||||
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;
|
||||
|
||||
free_defines(define_start);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -548,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;
|
||||
@@ -640,12 +913,12 @@ 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) {
|
||||
sv.r = op->reg;
|
||||
if ((op->vt->r & VT_VALMASK) == VT_LLOCAL)
|
||||
if ((op->vt->r & VT_VALMASK) == VT_LLOCAL && op->is_memory)
|
||||
sv.r |= VT_LVAL;
|
||||
}
|
||||
subst_asm_operand(out_str, &sv, modifier);
|
||||
@@ -669,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 == '[') {
|
||||
@@ -690,12 +963,14 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
||||
if (is_output) {
|
||||
test_lvalue();
|
||||
} else {
|
||||
/* we want to avoid LLOCAL case. note that it may come
|
||||
from register storage, so we need to convert (reg)
|
||||
/* we want to avoid LLOCAL case, except when the 'm'
|
||||
constraint is used. Note that it may come from
|
||||
register storage, so we need to convert (reg)
|
||||
case */
|
||||
if ((vtop->r & VT_LVAL) &&
|
||||
((vtop->r & VT_VALMASK) == VT_LLOCAL ||
|
||||
(vtop->r & VT_VALMASK) < VT_CONST)) {
|
||||
(vtop->r & VT_VALMASK) < VT_CONST) &&
|
||||
!strchr(op->constraint, 'm')) {
|
||||
gv(RC_INT);
|
||||
}
|
||||
}
|
||||
@@ -712,13 +987,11 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
||||
}
|
||||
|
||||
/* 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;
|
||||
uint8_t input_regs_allocated[NB_ASM_REGS];
|
||||
uint8_t output_regs_allocated[NB_ASM_REGS];
|
||||
int nb_outputs, nb_operands, i, must_subst, out_reg;
|
||||
uint8_t clobber_regs[NB_ASM_REGS];
|
||||
|
||||
next();
|
||||
@@ -727,42 +1000,36 @@ static void asm_instr(void)
|
||||
if (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3) {
|
||||
next();
|
||||
}
|
||||
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_asm_str(&astr);
|
||||
nb_operands = 0;
|
||||
nb_outputs = 0;
|
||||
must_subst = 0;
|
||||
memset(clobber_regs, 0, sizeof(clobber_regs));
|
||||
if (tok == ':') {
|
||||
next();
|
||||
must_subst = 1;
|
||||
/* output args */
|
||||
parse_asm_operands(operands, &nb_operands, 1);
|
||||
nb_outputs = nb_operands;
|
||||
if (tok == ':') {
|
||||
next();
|
||||
/* input args */
|
||||
parse_asm_operands(operands, &nb_operands, 0);
|
||||
if (tok == ':') {
|
||||
/* clobber list */
|
||||
/* XXX: handle registers */
|
||||
next();
|
||||
for(;;) {
|
||||
if (tok != TOK_STR)
|
||||
expect("string constant");
|
||||
asm_clobber(clobber_regs, tokc.cstr->data);
|
||||
if (tok != ')') {
|
||||
/* input args */
|
||||
parse_asm_operands(operands, &nb_operands, 0);
|
||||
if (tok == ':') {
|
||||
/* clobber list */
|
||||
/* XXX: handle registers */
|
||||
next();
|
||||
if (tok == ',') {
|
||||
for(;;) {
|
||||
if (tok != TOK_STR)
|
||||
expect("string constant");
|
||||
asm_clobber(clobber_regs, tokc.cstr->data);
|
||||
next();
|
||||
} else {
|
||||
break;
|
||||
if (tok == ',') {
|
||||
next();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -773,25 +1040,20 @@ 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);
|
||||
|
||||
/* compute constraints */
|
||||
asm_compute_constraints(input_regs_allocated,
|
||||
operands, nb_operands, nb_outputs, 0,
|
||||
NULL);
|
||||
asm_compute_constraints(output_regs_allocated,
|
||||
operands, nb_operands, nb_outputs, 1,
|
||||
input_regs_allocated);
|
||||
asm_compute_constraints(operands, nb_operands, nb_outputs,
|
||||
clobber_regs, &out_reg);
|
||||
|
||||
/* substitute the operands in the asm string. No substitution is
|
||||
done if no operands (GCC behaviour) */
|
||||
#ifdef ASM_DEBUG
|
||||
printf("asm: \"%s\"\n", (char *)astr.data);
|
||||
#endif
|
||||
if (nb_operands > 0) {
|
||||
if (must_subst) {
|
||||
subst_asm_operands(operands, nb_operands, nb_outputs, &astr1, &astr);
|
||||
cstr_free(&astr);
|
||||
} else {
|
||||
@@ -802,7 +1064,8 @@ static void asm_instr(void)
|
||||
#endif
|
||||
|
||||
/* generate loads */
|
||||
asm_gen_code(operands, nb_operands, nb_outputs, 0, clobber_regs);
|
||||
asm_gen_code(operands, nb_operands, nb_outputs, 0,
|
||||
clobber_regs, out_reg);
|
||||
|
||||
/* assemble the string with tcc internal assembler */
|
||||
tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1);
|
||||
@@ -811,7 +1074,8 @@ static void asm_instr(void)
|
||||
next();
|
||||
|
||||
/* store the output values if needed */
|
||||
asm_gen_code(operands, nb_operands, nb_outputs, 1, clobber_regs);
|
||||
asm_gen_code(operands, nb_operands, nb_outputs, 1,
|
||||
clobber_regs, out_reg);
|
||||
|
||||
/* free everything */
|
||||
for(i=0;i<nb_operands;i++) {
|
||||
@@ -823,3 +1087,32 @@ static void asm_instr(void)
|
||||
cstr_free(&astr1);
|
||||
}
|
||||
|
||||
ST_FUNC void asm_global_instr(void)
|
||||
{
|
||||
CString astr;
|
||||
|
||||
next();
|
||||
parse_asm_str(&astr);
|
||||
skip(')');
|
||||
/* NOTE: we do not eat the ';' so that we can restore the current
|
||||
token after the assembler parsing */
|
||||
if (tok != ';')
|
||||
expect("';'");
|
||||
|
||||
#ifdef ASM_DEBUG
|
||||
printf("asm_global: \"%s\"\n", (char *)astr.data);
|
||||
#endif
|
||||
cur_text_section = text_section;
|
||||
ind = cur_text_section->data_offset;
|
||||
|
||||
/* assemble the string with tcc internal assembler */
|
||||
tcc_assemble_inline(tcc_state, astr.data, astr.size - 1);
|
||||
|
||||
cur_text_section->data_offset = ind;
|
||||
|
||||
/* restore the current C token */
|
||||
next();
|
||||
|
||||
cstr_free(&astr);
|
||||
}
|
||||
#endif /* CONFIG_TCC_ASM */
|
||||
|
||||
948
tcccoff.c
Normal file
948
tcccoff.c
Normal file
@@ -0,0 +1,948 @@
|
||||
/*
|
||||
* COFF file handling for TCC
|
||||
*
|
||||
* Copyright (c) 2003, 2004 TK
|
||||
* Copyright (c) 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"
|
||||
|
||||
#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
|
||||
#define MAX_STR_TABLE 1000000
|
||||
AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */
|
||||
|
||||
SCNHDR section_header[MAXNSCNS];
|
||||
|
||||
#define MAX_FUNCS 1000
|
||||
#define MAX_FUNC_NAME_LENGTH 128
|
||||
|
||||
int nFuncs;
|
||||
char Func[MAX_FUNCS][MAX_FUNC_NAME_LENGTH];
|
||||
char AssociatedFile[MAX_FUNCS][MAX_FUNC_NAME_LENGTH];
|
||||
int LineNoFilePtr[MAX_FUNCS];
|
||||
int EndAddress[MAX_FUNCS];
|
||||
int LastLineNo[MAX_FUNCS];
|
||||
int FuncEntries[MAX_FUNCS];
|
||||
|
||||
int OutputTheSection(Section * sect);
|
||||
short int GetCoffFlags(const char *s);
|
||||
void SortSymbolTable(void);
|
||||
Section *FindSection(TCCState * s1, const char *sname);
|
||||
|
||||
int C67_main_entry_point;
|
||||
|
||||
int FindCoffSymbolIndex(const char *func_name);
|
||||
int nb_syms;
|
||||
|
||||
typedef struct {
|
||||
long tag;
|
||||
long size;
|
||||
long fileptr;
|
||||
long nextsym;
|
||||
short int dummy;
|
||||
} AUXFUNC;
|
||||
|
||||
typedef struct {
|
||||
long regmask;
|
||||
unsigned short lineno;
|
||||
unsigned short nentries;
|
||||
int localframe;
|
||||
int nextentry;
|
||||
short int dummy;
|
||||
} AUXBF;
|
||||
|
||||
typedef struct {
|
||||
long dummy;
|
||||
unsigned short lineno;
|
||||
unsigned short dummy1;
|
||||
int dummy2;
|
||||
int dummy3;
|
||||
unsigned short dummy4;
|
||||
} AUXEF;
|
||||
|
||||
ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
||||
{
|
||||
Section *tcc_sect;
|
||||
SCNHDR *coff_sec;
|
||||
int file_pointer;
|
||||
char *Coff_str_table, *pCoff_str_table;
|
||||
int CoffTextSectionNo, coff_nb_syms;
|
||||
FILHDR file_hdr; /* FILE HEADER STRUCTURE */
|
||||
Section *stext, *sdata, *sbss;
|
||||
int i, NSectionsToOutput = 0;
|
||||
|
||||
Coff_str_table = pCoff_str_table = NULL;
|
||||
|
||||
stext = FindSection(s1, ".text");
|
||||
sdata = FindSection(s1, ".data");
|
||||
sbss = FindSection(s1, ".bss");
|
||||
|
||||
nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
|
||||
coff_nb_syms = FindCoffSymbolIndex("XXXXXXXXXX1");
|
||||
|
||||
file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */
|
||||
file_hdr.f_timdat = 0; /* time & date stamp */
|
||||
file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */
|
||||
file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */
|
||||
file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */
|
||||
|
||||
o_filehdr.magic = 0x0108; /* see magic.h */
|
||||
o_filehdr.vstamp = 0x0190; /* version stamp */
|
||||
o_filehdr.tsize = stext->data_offset; /* text size in bytes, padded to FW bdry */
|
||||
o_filehdr.dsize = sdata->data_offset; /* initialized data " " */
|
||||
o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */
|
||||
o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */
|
||||
o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */
|
||||
o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */
|
||||
|
||||
|
||||
// create all the section headers
|
||||
|
||||
file_pointer = FILHSZ + sizeof(AOUTHDR);
|
||||
|
||||
CoffTextSectionNo = -1;
|
||||
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
if (OutputTheSection(tcc_sect)) {
|
||||
NSectionsToOutput++;
|
||||
|
||||
if (CoffTextSectionNo == -1 && tcc_sect == stext)
|
||||
CoffTextSectionNo = NSectionsToOutput; // rem which coff sect number the .text sect is
|
||||
|
||||
strcpy(coff_sec->s_name, tcc_sect->name); /* section name */
|
||||
|
||||
coff_sec->s_paddr = tcc_sect->sh_addr; /* physical address */
|
||||
coff_sec->s_vaddr = tcc_sect->sh_addr; /* virtual address */
|
||||
coff_sec->s_size = tcc_sect->data_offset; /* section size */
|
||||
coff_sec->s_scnptr = 0; /* file ptr to raw data for section */
|
||||
coff_sec->s_relptr = 0; /* file ptr to relocation */
|
||||
coff_sec->s_lnnoptr = 0; /* file ptr to line numbers */
|
||||
coff_sec->s_nreloc = 0; /* number of relocation entries */
|
||||
coff_sec->s_flags = GetCoffFlags(coff_sec->s_name); /* flags */
|
||||
coff_sec->s_reserved = 0; /* reserved byte */
|
||||
coff_sec->s_page = 0; /* memory page id */
|
||||
|
||||
file_pointer += sizeof(SCNHDR);
|
||||
}
|
||||
}
|
||||
|
||||
file_hdr.f_nscns = NSectionsToOutput; /* number of sections */
|
||||
|
||||
// now loop through and determine file pointer locations
|
||||
// for the raw data
|
||||
|
||||
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
if (OutputTheSection(tcc_sect)) {
|
||||
// put raw data
|
||||
coff_sec->s_scnptr = file_pointer; /* file ptr to raw data for section */
|
||||
file_pointer += coff_sec->s_size;
|
||||
}
|
||||
}
|
||||
|
||||
// now loop through and determine file pointer locations
|
||||
// for the relocation data
|
||||
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
if (OutputTheSection(tcc_sect)) {
|
||||
// put relocations data
|
||||
if (coff_sec->s_nreloc > 0) {
|
||||
coff_sec->s_relptr = file_pointer; /* file ptr to relocation */
|
||||
file_pointer += coff_sec->s_nreloc * sizeof(struct reloc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now loop through and determine file pointer locations
|
||||
// for the line number data
|
||||
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
coff_sec->s_nlnno = 0;
|
||||
coff_sec->s_lnnoptr = 0;
|
||||
|
||||
if (s1->do_debug && tcc_sect == stext) {
|
||||
// count how many line nos data
|
||||
|
||||
// also find association between source file name and function
|
||||
// so we can sort the symbol table
|
||||
|
||||
|
||||
Stab_Sym *sym, *sym_end;
|
||||
char func_name[MAX_FUNC_NAME_LENGTH],
|
||||
last_func_name[MAX_FUNC_NAME_LENGTH];
|
||||
unsigned long func_addr, last_pc, pc;
|
||||
const char *incl_files[INCLUDE_STACK_SIZE];
|
||||
int incl_index, len, last_line_num;
|
||||
const char *str, *p;
|
||||
|
||||
coff_sec->s_lnnoptr = file_pointer; /* file ptr to linno */
|
||||
|
||||
|
||||
func_name[0] = '\0';
|
||||
func_addr = 0;
|
||||
incl_index = 0;
|
||||
last_func_name[0] = '\0';
|
||||
last_pc = 0xffffffff;
|
||||
last_line_num = 1;
|
||||
sym = (Stab_Sym *) stab_section->data + 1;
|
||||
sym_end =
|
||||
(Stab_Sym *) (stab_section->data +
|
||||
stab_section->data_offset);
|
||||
|
||||
nFuncs = 0;
|
||||
while (sym < sym_end) {
|
||||
switch (sym->n_type) {
|
||||
/* function start or end */
|
||||
case N_FUN:
|
||||
if (sym->n_strx == 0) {
|
||||
// end of function
|
||||
|
||||
coff_sec->s_nlnno++;
|
||||
file_pointer += LINESZ;
|
||||
|
||||
pc = sym->n_value + func_addr;
|
||||
func_name[0] = '\0';
|
||||
func_addr = 0;
|
||||
EndAddress[nFuncs] = pc;
|
||||
FuncEntries[nFuncs] =
|
||||
(file_pointer -
|
||||
LineNoFilePtr[nFuncs]) / LINESZ - 1;
|
||||
LastLineNo[nFuncs++] = last_line_num + 1;
|
||||
} else {
|
||||
// beginning of function
|
||||
|
||||
LineNoFilePtr[nFuncs] = file_pointer;
|
||||
coff_sec->s_nlnno++;
|
||||
file_pointer += LINESZ;
|
||||
|
||||
str =
|
||||
(const char *) stabstr_section->data +
|
||||
sym->n_strx;
|
||||
|
||||
p = strchr(str, ':');
|
||||
if (!p) {
|
||||
pstrcpy(func_name, sizeof(func_name), str);
|
||||
pstrcpy(Func[nFuncs], sizeof(func_name), str);
|
||||
} else {
|
||||
len = p - str;
|
||||
if (len > sizeof(func_name) - 1)
|
||||
len = sizeof(func_name) - 1;
|
||||
memcpy(func_name, str, len);
|
||||
memcpy(Func[nFuncs], str, len);
|
||||
func_name[len] = '\0';
|
||||
}
|
||||
|
||||
// save the file that it came in so we can sort later
|
||||
pstrcpy(AssociatedFile[nFuncs], sizeof(func_name),
|
||||
incl_files[incl_index - 1]);
|
||||
|
||||
func_addr = sym->n_value;
|
||||
}
|
||||
break;
|
||||
|
||||
/* line number info */
|
||||
case N_SLINE:
|
||||
pc = sym->n_value + func_addr;
|
||||
|
||||
last_pc = pc;
|
||||
last_line_num = sym->n_desc;
|
||||
|
||||
/* XXX: slow! */
|
||||
strcpy(last_func_name, func_name);
|
||||
|
||||
coff_sec->s_nlnno++;
|
||||
file_pointer += LINESZ;
|
||||
break;
|
||||
/* include files */
|
||||
case N_BINCL:
|
||||
str =
|
||||
(const char *) stabstr_section->data + 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 =
|
||||
(const char *) stabstr_section->data +
|
||||
sym->n_strx;
|
||||
/* do not add path */
|
||||
len = strlen(str);
|
||||
if (len > 0 && str[len - 1] != '/')
|
||||
goto add_incl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
sym++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
file_hdr.f_symptr = file_pointer; /* file pointer to symtab */
|
||||
|
||||
if (s1->do_debug)
|
||||
file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */
|
||||
else
|
||||
file_hdr.f_nsyms = 0;
|
||||
|
||||
file_pointer += file_hdr.f_nsyms * SYMNMLEN;
|
||||
|
||||
// OK now we are all set to write the file
|
||||
|
||||
|
||||
fwrite(&file_hdr, FILHSZ, 1, f);
|
||||
fwrite(&o_filehdr, sizeof(o_filehdr), 1, f);
|
||||
|
||||
// write section headers
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
if (OutputTheSection(tcc_sect)) {
|
||||
fwrite(coff_sec, sizeof(SCNHDR), 1, f);
|
||||
}
|
||||
}
|
||||
|
||||
// write raw data
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
if (OutputTheSection(tcc_sect)) {
|
||||
fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f);
|
||||
}
|
||||
}
|
||||
|
||||
// write relocation data
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
if (OutputTheSection(tcc_sect)) {
|
||||
// put relocations data
|
||||
if (coff_sec->s_nreloc > 0) {
|
||||
fwrite(tcc_sect->reloc,
|
||||
coff_sec->s_nreloc * sizeof(struct reloc), 1, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// group the symbols in order of filename, func1, func2, etc
|
||||
// finally global symbols
|
||||
|
||||
if (s1->do_debug)
|
||||
SortSymbolTable();
|
||||
|
||||
// write line no data
|
||||
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
if (s1->do_debug && tcc_sect == stext) {
|
||||
// count how many line nos data
|
||||
|
||||
|
||||
Stab_Sym *sym, *sym_end;
|
||||
char func_name[128], last_func_name[128];
|
||||
unsigned long func_addr, last_pc, pc;
|
||||
const char *incl_files[INCLUDE_STACK_SIZE];
|
||||
int incl_index, len, last_line_num;
|
||||
const char *str, *p;
|
||||
|
||||
LINENO CoffLineNo;
|
||||
|
||||
func_name[0] = '\0';
|
||||
func_addr = 0;
|
||||
incl_index = 0;
|
||||
last_func_name[0] = '\0';
|
||||
last_pc = 0;
|
||||
last_line_num = 1;
|
||||
sym = (Stab_Sym *) stab_section->data + 1;
|
||||
sym_end =
|
||||
(Stab_Sym *) (stab_section->data +
|
||||
stab_section->data_offset);
|
||||
|
||||
while (sym < sym_end) {
|
||||
switch (sym->n_type) {
|
||||
/* function start or end */
|
||||
case N_FUN:
|
||||
if (sym->n_strx == 0) {
|
||||
// end of function
|
||||
|
||||
CoffLineNo.l_addr.l_paddr = last_pc;
|
||||
CoffLineNo.l_lnno = last_line_num + 1;
|
||||
fwrite(&CoffLineNo, 6, 1, f);
|
||||
|
||||
pc = sym->n_value + func_addr;
|
||||
func_name[0] = '\0';
|
||||
func_addr = 0;
|
||||
} else {
|
||||
// beginning of function
|
||||
|
||||
str =
|
||||
(const char *) stabstr_section->data +
|
||||
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;
|
||||
last_pc = func_addr;
|
||||
last_line_num = -1;
|
||||
|
||||
// output a function begin
|
||||
|
||||
CoffLineNo.l_addr.l_symndx =
|
||||
FindCoffSymbolIndex(func_name);
|
||||
CoffLineNo.l_lnno = 0;
|
||||
|
||||
fwrite(&CoffLineNo, 6, 1, f);
|
||||
}
|
||||
break;
|
||||
|
||||
/* line number info */
|
||||
case N_SLINE:
|
||||
pc = sym->n_value + func_addr;
|
||||
|
||||
|
||||
/* XXX: slow! */
|
||||
strcpy(last_func_name, func_name);
|
||||
|
||||
// output a line reference
|
||||
|
||||
CoffLineNo.l_addr.l_paddr = last_pc;
|
||||
|
||||
if (last_line_num == -1) {
|
||||
CoffLineNo.l_lnno = sym->n_desc;
|
||||
} else {
|
||||
CoffLineNo.l_lnno = last_line_num + 1;
|
||||
}
|
||||
|
||||
fwrite(&CoffLineNo, 6, 1, f);
|
||||
|
||||
last_pc = pc;
|
||||
last_line_num = sym->n_desc;
|
||||
|
||||
break;
|
||||
|
||||
/* include files */
|
||||
case N_BINCL:
|
||||
str =
|
||||
(const char *) stabstr_section->data + sym->n_strx;
|
||||
add_incl2:
|
||||
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 =
|
||||
(const char *) stabstr_section->data +
|
||||
sym->n_strx;
|
||||
/* do not add path */
|
||||
len = strlen(str);
|
||||
if (len > 0 && str[len - 1] != '/')
|
||||
goto add_incl2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
sym++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write symbol table
|
||||
if (s1->do_debug) {
|
||||
int k;
|
||||
struct syment csym;
|
||||
AUXFUNC auxfunc;
|
||||
AUXBF auxbf;
|
||||
AUXEF auxef;
|
||||
int i;
|
||||
Elf32_Sym *p;
|
||||
const char *name;
|
||||
int nstr;
|
||||
int n = 0;
|
||||
|
||||
Coff_str_table = (char *) tcc_malloc(MAX_STR_TABLE);
|
||||
pCoff_str_table = Coff_str_table;
|
||||
nstr = 0;
|
||||
|
||||
p = (Elf32_Sym *) symtab_section->data;
|
||||
|
||||
|
||||
for (i = 0; i < nb_syms; i++) {
|
||||
|
||||
name = symtab_section->link->data + p->st_name;
|
||||
|
||||
for (k = 0; k < 8; k++)
|
||||
csym._n._n_name[k] = 0;
|
||||
|
||||
if (strlen(name) <= 8) {
|
||||
strcpy(csym._n._n_name, name);
|
||||
} else {
|
||||
if (pCoff_str_table - Coff_str_table + strlen(name) >
|
||||
MAX_STR_TABLE - 1)
|
||||
tcc_error("String table too large");
|
||||
|
||||
csym._n._n_n._n_zeroes = 0;
|
||||
csym._n._n_n._n_offset =
|
||||
pCoff_str_table - Coff_str_table + 4;
|
||||
|
||||
strcpy(pCoff_str_table, name);
|
||||
pCoff_str_table += strlen(name) + 1; // skip over null
|
||||
nstr++;
|
||||
}
|
||||
|
||||
if (p->st_info == 4) {
|
||||
// put a filename symbol
|
||||
csym.n_value = 33; // ?????
|
||||
csym.n_scnum = N_DEBUG;
|
||||
csym.n_type = 0;
|
||||
csym.n_sclass = C_FILE;
|
||||
csym.n_numaux = 0;
|
||||
fwrite(&csym, 18, 1, f);
|
||||
n++;
|
||||
|
||||
} else if (p->st_info == 0x12) {
|
||||
// find the function data
|
||||
|
||||
for (k = 0; k < nFuncs; k++) {
|
||||
if (strcmp(name, Func[k]) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (k >= nFuncs) {
|
||||
tcc_error("debug info can't find function: %s", name);
|
||||
}
|
||||
// put a Function Name
|
||||
|
||||
csym.n_value = p->st_value; // physical address
|
||||
csym.n_scnum = CoffTextSectionNo;
|
||||
csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0);
|
||||
csym.n_sclass = C_EXT;
|
||||
csym.n_numaux = 1;
|
||||
fwrite(&csym, 18, 1, f);
|
||||
|
||||
// now put aux info
|
||||
|
||||
auxfunc.tag = 0;
|
||||
auxfunc.size = EndAddress[k] - p->st_value;
|
||||
auxfunc.fileptr = LineNoFilePtr[k];
|
||||
auxfunc.nextsym = n + 6; // tktk
|
||||
auxfunc.dummy = 0;
|
||||
fwrite(&auxfunc, 18, 1, f);
|
||||
|
||||
// put a .bf
|
||||
|
||||
strcpy(csym._n._n_name, ".bf");
|
||||
csym.n_value = p->st_value; // physical address
|
||||
csym.n_scnum = CoffTextSectionNo;
|
||||
csym.n_type = 0;
|
||||
csym.n_sclass = C_FCN;
|
||||
csym.n_numaux = 1;
|
||||
fwrite(&csym, 18, 1, f);
|
||||
|
||||
// now put aux info
|
||||
|
||||
auxbf.regmask = 0;
|
||||
auxbf.lineno = 0;
|
||||
auxbf.nentries = FuncEntries[k];
|
||||
auxbf.localframe = 0;
|
||||
auxbf.nextentry = n + 6;
|
||||
auxbf.dummy = 0;
|
||||
fwrite(&auxbf, 18, 1, f);
|
||||
|
||||
// put a .ef
|
||||
|
||||
strcpy(csym._n._n_name, ".ef");
|
||||
csym.n_value = EndAddress[k]; // physical address
|
||||
csym.n_scnum = CoffTextSectionNo;
|
||||
csym.n_type = 0;
|
||||
csym.n_sclass = C_FCN;
|
||||
csym.n_numaux = 1;
|
||||
fwrite(&csym, 18, 1, f);
|
||||
|
||||
// now put aux info
|
||||
|
||||
auxef.dummy = 0;
|
||||
auxef.lineno = LastLineNo[k];
|
||||
auxef.dummy1 = 0;
|
||||
auxef.dummy2 = 0;
|
||||
auxef.dummy3 = 0;
|
||||
auxef.dummy4 = 0;
|
||||
fwrite(&auxef, 18, 1, f);
|
||||
|
||||
n += 6;
|
||||
|
||||
} else {
|
||||
// try an put some type info
|
||||
|
||||
if ((p->st_other & VT_BTYPE) == VT_DOUBLE) {
|
||||
csym.n_type = T_DOUBLE; // int
|
||||
csym.n_sclass = C_EXT;
|
||||
} else if ((p->st_other & VT_BTYPE) == VT_FLOAT) {
|
||||
csym.n_type = T_FLOAT;
|
||||
csym.n_sclass = C_EXT;
|
||||
} else if ((p->st_other & VT_BTYPE) == VT_INT) {
|
||||
csym.n_type = T_INT; // int
|
||||
csym.n_sclass = C_EXT;
|
||||
} else if ((p->st_other & VT_BTYPE) == VT_SHORT) {
|
||||
csym.n_type = T_SHORT;
|
||||
csym.n_sclass = C_EXT;
|
||||
} else if ((p->st_other & VT_BTYPE) == VT_BYTE) {
|
||||
csym.n_type = T_CHAR;
|
||||
csym.n_sclass = C_EXT;
|
||||
} else {
|
||||
csym.n_type = T_INT; // just mark as a label
|
||||
csym.n_sclass = C_LABEL;
|
||||
}
|
||||
|
||||
|
||||
csym.n_value = p->st_value;
|
||||
csym.n_scnum = 2;
|
||||
csym.n_numaux = 1;
|
||||
fwrite(&csym, 18, 1, f);
|
||||
|
||||
auxfunc.tag = 0;
|
||||
auxfunc.size = 0x20;
|
||||
auxfunc.fileptr = 0;
|
||||
auxfunc.nextsym = 0;
|
||||
auxfunc.dummy = 0;
|
||||
fwrite(&auxfunc, 18, 1, f);
|
||||
n++;
|
||||
n++;
|
||||
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (s1->do_debug) {
|
||||
// write string table
|
||||
|
||||
// first write the size
|
||||
i = pCoff_str_table - Coff_str_table;
|
||||
fwrite(&i, 4, 1, f);
|
||||
|
||||
// then write the strings
|
||||
fwrite(Coff_str_table, i, 1, f);
|
||||
|
||||
tcc_free(Coff_str_table);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// group the symbols in order of filename, func1, func2, etc
|
||||
// finally global symbols
|
||||
|
||||
void SortSymbolTable(void)
|
||||
{
|
||||
int i, j, k, n = 0;
|
||||
Elf32_Sym *p, *p2, *NewTable;
|
||||
char *name, *name2;
|
||||
|
||||
NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym));
|
||||
|
||||
p = (Elf32_Sym *) symtab_section->data;
|
||||
|
||||
|
||||
// find a file symbol, copy it over
|
||||
// then scan the whole symbol list and copy any function
|
||||
// symbols that match the file association
|
||||
|
||||
for (i = 0; i < nb_syms; i++) {
|
||||
if (p->st_info == 4) {
|
||||
name = (char *) symtab_section->link->data + p->st_name;
|
||||
|
||||
// this is a file symbol, copy it over
|
||||
|
||||
NewTable[n++] = *p;
|
||||
|
||||
p2 = (Elf32_Sym *) symtab_section->data;
|
||||
|
||||
for (j = 0; j < nb_syms; j++) {
|
||||
if (p2->st_info == 0x12) {
|
||||
// this is a func symbol
|
||||
|
||||
name2 =
|
||||
(char *) symtab_section->link->data + p2->st_name;
|
||||
|
||||
// find the function data index
|
||||
|
||||
for (k = 0; k < nFuncs; k++) {
|
||||
if (strcmp(name2, Func[k]) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (k >= nFuncs) {
|
||||
tcc_error("debug (sort) info can't find function: %s", name2);
|
||||
}
|
||||
|
||||
if (strcmp(AssociatedFile[k], name) == 0) {
|
||||
// yes they match copy it over
|
||||
|
||||
NewTable[n++] = *p2;
|
||||
}
|
||||
}
|
||||
p2++;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
// now all the filename and func symbols should have been copied over
|
||||
// copy all the rest over (all except file and funcs)
|
||||
|
||||
p = (Elf32_Sym *) symtab_section->data;
|
||||
for (i = 0; i < nb_syms; i++) {
|
||||
if (p->st_info != 4 && p->st_info != 0x12) {
|
||||
NewTable[n++] = *p;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if (n != nb_syms)
|
||||
tcc_error("Internal Compiler error, debug info");
|
||||
|
||||
// copy it all back
|
||||
|
||||
p = (Elf32_Sym *) symtab_section->data;
|
||||
for (i = 0; i < nb_syms; i++) {
|
||||
*p++ = NewTable[i];
|
||||
}
|
||||
|
||||
tcc_free(NewTable);
|
||||
}
|
||||
|
||||
|
||||
int FindCoffSymbolIndex(const char *func_name)
|
||||
{
|
||||
int i, n = 0;
|
||||
Elf32_Sym *p;
|
||||
char *name;
|
||||
|
||||
p = (Elf32_Sym *) symtab_section->data;
|
||||
|
||||
for (i = 0; i < nb_syms; i++) {
|
||||
|
||||
name = (char *) symtab_section->link->data + p->st_name;
|
||||
|
||||
if (p->st_info == 4) {
|
||||
// put a filename symbol
|
||||
n++;
|
||||
} else if (p->st_info == 0x12) {
|
||||
|
||||
if (strcmp(func_name, name) == 0)
|
||||
return n;
|
||||
|
||||
n += 6;
|
||||
|
||||
// put a Function Name
|
||||
|
||||
// now put aux info
|
||||
|
||||
// put a .bf
|
||||
|
||||
// now put aux info
|
||||
|
||||
// put a .ef
|
||||
|
||||
// now put aux info
|
||||
|
||||
} else {
|
||||
n += 2;
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
|
||||
return n; // total number of symbols
|
||||
}
|
||||
|
||||
int OutputTheSection(Section * sect)
|
||||
{
|
||||
const char *s = sect->name;
|
||||
|
||||
if (!strcmp(s, ".text"))
|
||||
return 1;
|
||||
else if (!strcmp(s, ".data"))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
short int GetCoffFlags(const char *s)
|
||||
{
|
||||
if (!strcmp(s, ".text"))
|
||||
return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400;
|
||||
else if (!strcmp(s, ".data"))
|
||||
return STYP_DATA;
|
||||
else if (!strcmp(s, ".bss"))
|
||||
return STYP_BSS;
|
||||
else if (!strcmp(s, ".stack"))
|
||||
return STYP_BSS | STYP_ALIGN | 0x200;
|
||||
else if (!strcmp(s, ".cinit"))
|
||||
return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
Section *FindSection(TCCState * s1, const char *sname)
|
||||
{
|
||||
Section *s;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
|
||||
if (!strcmp(sname, s->name))
|
||||
return s;
|
||||
}
|
||||
|
||||
tcc_error("could not find section %s", sname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ST_FUNC int tcc_load_coff(TCCState * s1, int fd)
|
||||
{
|
||||
// tktk TokenSym *ts;
|
||||
|
||||
FILE *f;
|
||||
unsigned int str_size;
|
||||
char *Coff_str_table, *name;
|
||||
int i, k;
|
||||
struct syment csym;
|
||||
char name2[9];
|
||||
FILHDR file_hdr; /* FILE HEADER STRUCTURE */
|
||||
|
||||
f = fdopen(fd, "rb");
|
||||
if (!f) {
|
||||
tcc_error("Unable to open .out file for input");
|
||||
}
|
||||
|
||||
if (fread(&file_hdr, FILHSZ, 1, f) != 1)
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1)
|
||||
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))
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
if (fread(&str_size, sizeof(int), 1, f) != 1)
|
||||
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)
|
||||
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))
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
for (i = 0; i < file_hdr.f_nsyms; i++) {
|
||||
if (fread(&csym, SYMESZ, 1, f) != 1)
|
||||
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;
|
||||
} else {
|
||||
name = csym._n._n_name;
|
||||
|
||||
if (name[7] != 0) {
|
||||
for (k = 0; k < 8; k++)
|
||||
name2[k] = name[k];
|
||||
|
||||
name2[8] = 0;
|
||||
|
||||
name = name2;
|
||||
}
|
||||
}
|
||||
// if (strcmp("_DAC_Buffer",name)==0) // tktk
|
||||
// name[0]=0;
|
||||
|
||||
if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || (csym.n_type == 0x4 && csym.n_sclass == 0x2) || (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures
|
||||
(csym.n_type == 0x18 && csym.n_sclass == 0x2) || // pointer to structure
|
||||
(csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles
|
||||
(csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats
|
||||
{
|
||||
// strip off any leading underscore (except for other main routine)
|
||||
|
||||
if (name[0] == '_' && strcmp(name, "_main") != 0)
|
||||
name++;
|
||||
|
||||
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)
|
||||
tcc_error("error reading .out file for input");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
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 */
|
||||
/* ------------------------------------------------------------- */
|
||||
359
tcctok.h
359
tcctok.h
@@ -64,6 +64,7 @@
|
||||
/* preprocessor only */
|
||||
DEF(TOK_DEFINE, "define")
|
||||
DEF(TOK_INCLUDE, "include")
|
||||
DEF(TOK_INCLUDE_NEXT, "include_next")
|
||||
DEF(TOK_IFDEF, "ifdef")
|
||||
DEF(TOK_IFNDEF, "ifndef")
|
||||
DEF(TOK_ELIF, "elif")
|
||||
@@ -80,16 +81,27 @@
|
||||
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")
|
||||
DEF(TOK_SECTION2, "__section__")
|
||||
DEF(TOK_ALIGNED1, "aligned")
|
||||
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")
|
||||
@@ -98,30 +110,113 @@
|
||||
DEF(TOK_STDCALL1, "stdcall")
|
||||
DEF(TOK_STDCALL2, "__stdcall")
|
||||
DEF(TOK_STDCALL3, "__stdcall__")
|
||||
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_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) && !defined(TCC_TARGET_X86_64)
|
||||
/* already defined for assembler */
|
||||
DEF(TOK_ASM_push, "push")
|
||||
DEF(TOK_ASM_pop, "pop")
|
||||
#endif
|
||||
|
||||
/* builtin functions or variables */
|
||||
#ifdef TCC_ARM_EABI
|
||||
DEF(TOK_memcpy, "__aeabi_memcpy")
|
||||
DEF(TOK_memcpy4, "__aeabi_memcpy4")
|
||||
DEF(TOK_memcpy8, "__aeabi_memcpy8")
|
||||
DEF(TOK_memset, "__aeabi_memset")
|
||||
DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")
|
||||
DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")
|
||||
#else
|
||||
DEF(TOK_memcpy, "memcpy")
|
||||
DEF(TOK_memset, "memset")
|
||||
DEF(TOK_alloca, "alloca")
|
||||
DEF(TOK___divdi3, "__divdi3")
|
||||
DEF(TOK___moddi3, "__moddi3")
|
||||
DEF(TOK___udivdi3, "__udivdi3")
|
||||
DEF(TOK___umoddi3, "__umoddi3")
|
||||
DEF(TOK___sardi3, "__sardi3")
|
||||
DEF(TOK___shrdi3, "__shrdi3")
|
||||
DEF(TOK___shldi3, "__shldi3")
|
||||
#endif
|
||||
#if defined(TCC_TARGET_ARM)
|
||||
#ifdef TCC_ARM_EABI
|
||||
DEF(TOK___aeabi_idivmod, "__aeabi_idivmod")
|
||||
DEF(TOK___aeabi_uidivmod, "__aeabi_uidivmod")
|
||||
DEF(TOK___divsi3, "__aeabi_idiv")
|
||||
DEF(TOK___udivsi3, "__aeabi_uidiv")
|
||||
DEF(TOK___floatdisf, "__aeabi_l2f")
|
||||
DEF(TOK___floatdidf, "__aeabi_l2d")
|
||||
DEF(TOK___fixsfdi, "__aeabi_f2lz")
|
||||
DEF(TOK___fixdfdi, "__aeabi_d2lz")
|
||||
#else
|
||||
DEF(TOK___modsi3, "__modsi3")
|
||||
DEF(TOK___umodsi3, "__umodsi3")
|
||||
DEF(TOK___divsi3, "__divsi3")
|
||||
DEF(TOK___udivsi3, "__udivsi3")
|
||||
DEF(TOK___floatdisf, "__floatdisf")
|
||||
DEF(TOK___floatdidf, "__floatdidf")
|
||||
#ifndef TCC_ARM_VFP
|
||||
DEF(TOK___floatdixf, "__floatdixf")
|
||||
DEF(TOK___fixunssfsi, "__fixunssfsi")
|
||||
DEF(TOK___fixunsdfsi, "__fixunsdfsi")
|
||||
DEF(TOK___fixunsxfsi, "__fixunsxfsi")
|
||||
DEF(TOK___fixxfdi, "__fixxfdi")
|
||||
#endif
|
||||
DEF(TOK___fixsfdi, "__fixsfdi")
|
||||
DEF(TOK___fixdfdi, "__fixdfdi")
|
||||
#endif
|
||||
#elif defined(TCC_TARGET_C67)
|
||||
DEF(TOK__divi, "_divi")
|
||||
DEF(TOK__divu, "_divu")
|
||||
DEF(TOK__divf, "_divf")
|
||||
DEF(TOK__divd, "_divd")
|
||||
DEF(TOK__remi, "_remi")
|
||||
DEF(TOK__remu, "_remu")
|
||||
#endif
|
||||
#ifdef TCC_TARGET_I386
|
||||
DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
|
||||
DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
|
||||
DEF(TOK___ulltof, "__ulltof")
|
||||
DEF(TOK___ulltod, "__ulltod")
|
||||
DEF(TOK___ulltold, "__ulltold")
|
||||
#endif
|
||||
#ifdef TCC_ARM_EABI
|
||||
DEF(TOK___ashrdi3, "__aeabi_lasr")
|
||||
DEF(TOK___lshrdi3, "__aeabi_llsr")
|
||||
DEF(TOK___ashldi3, "__aeabi_llsl")
|
||||
DEF(TOK___floatundisf, "__aeabi_ul2f")
|
||||
DEF(TOK___floatundidf, "__aeabi_ul2d")
|
||||
DEF(TOK___fixunssfdi, "__aeabi_f2ulz")
|
||||
DEF(TOK___fixunsdfdi, "__aeabi_d2ulz")
|
||||
#else
|
||||
DEF(TOK___ashrdi3, "__ashrdi3")
|
||||
DEF(TOK___lshrdi3, "__lshrdi3")
|
||||
DEF(TOK___ashldi3, "__ashldi3")
|
||||
DEF(TOK___floatundisf, "__floatundisf")
|
||||
DEF(TOK___floatundidf, "__floatundidf")
|
||||
#ifndef TCC_ARM_VFP
|
||||
DEF(TOK___floatundixf, "__floatundixf")
|
||||
DEF(TOK___fixunsxfdi, "__fixunsxfdi")
|
||||
#endif
|
||||
DEF(TOK___fixunssfdi, "__fixunssfdi")
|
||||
DEF(TOK___fixunsdfdi, "__fixunsdfdi")
|
||||
DEF(TOK___fixunsxfdi, "__fixunsxfdi")
|
||||
#endif
|
||||
#ifdef TCC_TARGET_PE
|
||||
DEF(TOK___chkstk, "__chkstk")
|
||||
#endif
|
||||
|
||||
/* bound checking symbols */
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
@@ -134,242 +229,50 @@
|
||||
DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
|
||||
DEF(TOK___bound_local_new, "__bound_local_new")
|
||||
DEF(TOK___bound_local_delete, "__bound_local_delete")
|
||||
#ifdef TCC_TARGET_PE
|
||||
DEF(TOK_malloc, "malloc")
|
||||
DEF(TOK_free, "free")
|
||||
DEF(TOK_realloc, "realloc")
|
||||
DEF(TOK_memalign, "memalign")
|
||||
DEF(TOK_calloc, "calloc")
|
||||
#endif
|
||||
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)
|
||||
|
||||
#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"
|
||||
|
||||
DEF_ASM(previous)
|
||||
DEF_ASM(fill)
|
||||
DEF_ASM(org)
|
||||
DEF_ASM(quad)
|
||||
#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
|
||||
|
||||
199
tests/Makefile
Normal file
199
tests/Makefile
Normal file
@@ -0,0 +1,199 @@
|
||||
#
|
||||
# Tiny C Compiler Makefile - tests
|
||||
#
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
hello-exe: ../examples/ex1.c
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) $< -o hello$(EXESUF) || ($(TOP)/tcc -vv; exit 1) && ./hello$(EXESUF)
|
||||
|
||||
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 ../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
|
||||
test1: test.ref
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) -run tcctest.c > test.out1
|
||||
@if diff -u test.ref test.out1 ; then echo "Auto Test OK"; fi
|
||||
|
||||
# iterated test2 (compile tcc then compile tcctest.c !)
|
||||
test2: test.ref
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) $(RUN_TCC) $(RUN_TCC) -run tcctest.c > test.out2
|
||||
@if diff -u test.ref test.out2 ; then echo "Auto Test2 OK"; fi
|
||||
|
||||
# iterated test3 (compile tcc then compile tcc then compile tcctest.c !)
|
||||
test3: test.ref
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run tcctest.c > test.out3
|
||||
@if diff -u test.ref test.out3 ; then echo "Auto Test3 OK"; fi
|
||||
|
||||
# binary output test
|
||||
test4: test.ref
|
||||
@echo ------------ $@ ------------
|
||||
# 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
|
||||
# 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 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 \
|
||||
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\
|
||||
echo failed as expected; \
|
||||
fi ;\
|
||||
done ;\
|
||||
echo; echo Bound test OK
|
||||
|
||||
# speed test
|
||||
speedtest: ex2 ex3
|
||||
@echo ------------ $@ ------------
|
||||
time ./ex2 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 $(top_srcdir)/examples/ex3.c 35
|
||||
|
||||
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) -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 > asmtest.out
|
||||
@if diff -u --ignore-matching-lines="file format" asmtest.ref asmtest.out ; then echo "ASM Auto Test OK"; fi
|
||||
|
||||
# targets for development
|
||||
%.bin: %.c tcc
|
||||
$(TCC) -g -o $@ $<
|
||||
$(DISAS) $@
|
||||
|
||||
instr: instr.o
|
||||
objdump -d instr.o
|
||||
|
||||
instr.o: instr.S
|
||||
$(CC) -o $@ -c $< -O2 -Wall -g
|
||||
|
||||
cache: tcc_g
|
||||
cachegrind ./tcc_g -o /tmp/linpack -lm bench/linpack.c
|
||||
vg_annotate tcc.c > /tmp/linpack.cache.log
|
||||
|
||||
# clean
|
||||
clean:
|
||||
$(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"
|
||||
@@ -43,6 +45,8 @@ movl $2, 0x100(%ebx,%edx,2)
|
||||
movl %eax, 0x100(%ebx,%edx,2)
|
||||
movl 0x100(%ebx,%edx,2), %edx
|
||||
movw %ax, 0x100(%ebx,%edx,2)
|
||||
|
||||
mov %eax, 0x12(,%edx,2)
|
||||
|
||||
mov %cr3, %edx
|
||||
mov %ecx, %cr3
|
||||
@@ -119,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)
|
||||
@@ -194,6 +199,11 @@ call *%eax
|
||||
call *0x1000
|
||||
call func1
|
||||
|
||||
.global L5,L6
|
||||
|
||||
L5:
|
||||
L6:
|
||||
|
||||
lcall $0x100, $0x1000
|
||||
|
||||
jmp 0x1000
|
||||
@@ -203,8 +213,10 @@ jmp *0x1000
|
||||
ljmp $0x100, $0x1000
|
||||
|
||||
ret
|
||||
retl
|
||||
|
||||
ret $10
|
||||
retl $10
|
||||
|
||||
lret
|
||||
|
||||
@@ -238,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
|
||||
@@ -339,9 +355,9 @@ L3:
|
||||
fnstcw 0x1002
|
||||
fstcw 0x1002
|
||||
fnstsw 0x1004
|
||||
fnstsw %eax
|
||||
fnstsw (%eax)
|
||||
fstsw 0x1004
|
||||
fstsw %eax
|
||||
fstsw (%eax)
|
||||
fnclex
|
||||
fclex
|
||||
fnstenv 0x1000
|
||||
@@ -468,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
|
||||
@@ -520,6 +554,8 @@ int $0x10
|
||||
bts %edx, 0x1000
|
||||
btsl $2, 0x1000
|
||||
|
||||
|
||||
|
||||
boundl %edx, 0x10000
|
||||
boundw %bx, 0x1000
|
||||
|
||||
@@ -540,3 +576,34 @@ int $0x10
|
||||
|
||||
verr 0x1000
|
||||
verw 0x1000
|
||||
|
||||
push %ds
|
||||
pushw %ds
|
||||
pushl %ds
|
||||
pop %ds
|
||||
popw %ds
|
||||
popl %ds
|
||||
fxsave 1(%ebx)
|
||||
fxrstor 1(%ecx)
|
||||
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
gcctestsuite.sh → tests/gcctestsuite.sh
Executable file → Normal file
8
gcctestsuite.sh → tests/gcctestsuite.sh
Executable file → Normal file
@@ -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
|
||||
@@ -5,8 +5,9 @@
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libtcc.h>
|
||||
#include "libtcc.h"
|
||||
|
||||
/* this function is called by the generated code */
|
||||
int add(int a, int b)
|
||||
@@ -14,7 +15,7 @@ int add(int a, int b)
|
||||
return a + b;
|
||||
}
|
||||
|
||||
char my_program[] =
|
||||
char my_program[] =
|
||||
"int fib(int n)\n"
|
||||
"{\n"
|
||||
" if (n <= 2)\n"
|
||||
@@ -35,31 +36,41 @@ int main(int argc, char **argv)
|
||||
{
|
||||
TCCState *s;
|
||||
int (*func)(int);
|
||||
unsigned long val;
|
||||
|
||||
|
||||
s = tcc_new();
|
||||
if (!s) {
|
||||
fprintf(stderr, "Could not create tcc state\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* MUST BE CALLED before any compilation or file loading */
|
||||
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
|
||||
if (argc == 2 && !memcmp(argv[1], "lib_path=",9))
|
||||
tcc_set_lib_path(s, argv[1]+9);
|
||||
|
||||
/* MUST BE CALLED before any compilation */
|
||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||
|
||||
tcc_compile_string(s, my_program);
|
||||
if (tcc_compile_string(s, my_program) == -1)
|
||||
return 1;
|
||||
|
||||
/* as a test, we add a symbol that the compiled program can be
|
||||
linked with. You can have a similar result by opening a dll
|
||||
with tcc_add_dll(() and using its symbols directly. */
|
||||
tcc_add_symbol(s, "add", (unsigned long)&add);
|
||||
|
||||
tcc_relocate(s);
|
||||
/* as a test, we add a symbol that the compiled program can use.
|
||||
You may also open a dll with tcc_add_dll() and use symbols from that */
|
||||
tcc_add_symbol(s, "add", add);
|
||||
|
||||
tcc_get_symbol(s, &val, "foo");
|
||||
func = (void *)val;
|
||||
/* relocate the code */
|
||||
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
|
||||
return 1;
|
||||
|
||||
/* get entry symbol */
|
||||
func = tcc_get_symbol(s, "foo");
|
||||
if (!func)
|
||||
return 1;
|
||||
|
||||
/* run the code */
|
||||
func(32);
|
||||
|
||||
/* delete the state */
|
||||
tcc_delete(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user