History

div fixes

- Makefile: don't produce unknown targets - libtcc.c: tcc_set_linker(): improve parser - tcc.h: tcc_internal_error(): don't record __FILE__ (for privacy reasons) - tccgen.c: - reject pointer + float operation - use 'int level' for builtin_frame/return_address - save_regs(): remove VT_ARRAY (confuses riscv64-gen) - tccpe.c: store just basename of loaded dlls (rather than full path) - tccpp.c: remove unused TAL defines - *-link.c: add missing ST_FUNC - i386-gen.c: fix thiscall - riscv64-asm.c/arm-asm.c: stay simple C89 - avoid .designators, decl after statement - avoid multiple instances of same static const objects - use skip() instead of next() & expect() - use cstr_printf() instead of snprintf() & cstr_cat() - tcc_error(), expect(): never return

grischka committed 2 years ago

Commit 6b78e561 parent 3b943be20 files · +227 −508Browse files

Unified · Split

20 files
  1. Makefile +1 −0
  2. arm-asm.c +28 −193
  3. arm-link.c +3 −3
  4. arm64-link.c +3 −3
  5. c67-link.c +3 −3
  6. i386-asm.c +6 −19
  7. i386-gen.c +8 −24
  8. i386-link.c +3 −3
  9. libtcc.c +27 −17
  10. riscv64-asm.c +28 −108
  11. riscv64-link.c +3 −3
  12. tcc.h +4 −5
  13. tccelf.c +9 −20
  14. tccgen.c +51 −54
  15. tccpe.c +5 −2
  16. tccpp.c +32 −31
  17. tests/tests2/60_errors_and_warnings.c +7 −0
  18. tests/tests2/60_errors_and_warnings.expect +3 −0
  19. tests/thiscall/thiscall-test.c +0 −17
  20. x86_64-link.c +3 −3
Makefile+1−0
@@ -198,6 +198,7 @@ DEFINES += $(if $(ELF-$T),-DCONFIG_TCC_ELFINTERP="\"$(ELF-$T)\"") · 197 unmodified lines
198198 DEFINES += $(DEF-$(or $(findstring win,$T),unx))
199199
200200 ifneq ($(X),)
201+$(if $(DEF-$T),,$(error error: unknown target: '$T'))
201202 DEF-all += -DCONFIG_TCC_CROSSPREFIX="\"$X\""
202203 ifneq ($(CONFIG_WIN32),yes)
203204 DEF-win += -DCONFIG_TCCDIR="\"$(tccdir)/win32\""
arm-asm.c+28−193
@@ -92,7 +92,6 @@ static void parse_operand(TCCState *s1, Operand *op) · 91 unmodified lines
9292 reg = asm_parse_regvar(tok);
9393 if (reg == -1) {
9494 expect("register");
95− return;
9695 } else
9796 next(); // skip register name
9897
@@ -103,9 +102,7 @@ static void parse_operand(TCCState *s1, Operand *op) · 4 unmodified lines
103102 break;
104103 next(); // skip ','
105104 }
106− if (tok != '}')
107− expect("'}'");
108− next(); // skip '}'
105+ skip('}');
109106 if (regset == 0) {
110107 // ARM instructions don't support empty regset.
111108 tcc_error("empty register list is not supported");
@@ -186,7 +183,6 @@ ST_FUNC void gen_expr32(ExprValue *pe) · 74 unmodified lines
186183 static uint32_t condition_code_of_token(int token) {
187184 if (token < TOK_ASM_nopeq) {
188185 expect("condition-enabled instruction");
189− return 0;
190186 } else
191187 return (token - TOK_ASM_nopeq) & 15;
192188 }
@@ -262,19 +258,14 @@ static void asm_binary_opcode(TCCState *s1, int token) · 69 unmodified lines
262258 uint32_t encoded_rotation = 0;
263259 uint64_t amount;
264260 parse_operand(s1, &ops[0]);
265− if (tok == ',')
266− next();
267− else
268− expect("','");
261+ skip(',');
269262 parse_operand(s1, &ops[1]);
270263 if (ops[0].type != OP_REG32) {
271264 expect("(destination operand) register");
272− return;
273265 }
274266
275267 if (ops[0].reg == 15) {
276268 tcc_error("'%s' does not support 'pc' as operand", get_tok_str(token, NULL));
277− return;
278269 }
279270
280271 if (ops[0].reg == 13)
@@ -308,7 +299,6 @@ static void asm_binary_opcode(TCCState *s1, int token) · 27 unmodified lines
308299
309300 if (ops[1].reg == 15) {
310301 tcc_error("'%s' does not support 'pc' as operand", get_tok_str(token, NULL));
311− return;
312302 }
313303
314304 if (ops[1].reg == 13)
@@ -321,7 +311,6 @@ static void asm_binary_opcode(TCCState *s1, int token) · 6 unmodified lines
321311 parse_operand(s1, &rotation);
322312 if (rotation.type != OP_IM8) {
323313 expect("immediate value for rotation");
324− return;
325314 } else {
326315 amount = rotation.e.v;
327316 switch (amount) {
@@ -336,7 +325,6 @@ static void asm_binary_opcode(TCCState *s1, int token) · 8 unmodified lines
336325 break;
337326 default:
338327 expect("'8' or '16' or '24'");
339− return;
340328 }
341329 }
342330 }
@@ -378,32 +366,21 @@ static void asm_coprocessor_opcode(TCCState *s1, int token) { · 35 unmodified lines
378366 next();
379367 } else {
380368 expect("'p<number>'");
381− return;
382369 }
383−
384− if (tok == ',')
385− next();
386− else
387− expect("','");
388−
370+ skip(',');
389371 parse_operand(s1, &opcode1);
390372 if (opcode1.type != OP_IM8 || opcode1.e.v > 15) {
391373 tcc_error("opcode1 of instruction '%s' must be an immediate value between 0 and 15", get_tok_str(token, NULL));
392− return;
393374 }
394375
395376 for (i = 0; i < 3; ++i) {
396− if (tok == ',')
397− next();
398− else
399− expect("','");
377+ skip(',');
400378 if (i == 0 && token != TOK_ASM_cdp2 && (ARM_INSTRUCTION_GROUP(token) == TOK_ASM_mrceq || ARM_INSTRUCTION_GROUP(token) == TOK_ASM_mcreq)) {
401379 if (tok >= TOK_ASM_r0 && tok <= TOK_ASM_r15) {
402380 registers[i] = tok - TOK_ASM_r0;
403381 next();
404382 } else {
405383 expect("'r<number>'");
406− return;
407384 }
408385 } else {
409386 if (tok >= TOK_ASM_c0 && tok <= TOK_ASM_c15) {
@@ -411,7 +388,6 @@ static void asm_coprocessor_opcode(TCCState *s1, int token) { · 1 unmodified line
411388 next();
412389 } else {
413390 expect("'c<number>'");
414− return;
415391 }
416392 }
417393 }
@@ -424,7 +400,6 @@ static void asm_coprocessor_opcode(TCCState *s1, int token) { · 6 unmodified lines
424400 }
425401 if (opcode2.type != OP_IM8 || opcode2.e.v > 15) {
426402 tcc_error("opcode2 of instruction '%s' must be an immediate value between 0 and 15", get_tok_str(token, NULL));
427− return;
428403 }
429404
430405 if (token == TOK_ASM_cdp2) {
@@ -446,7 +421,6 @@ static void asm_coprocessor_opcode(TCCState *s1, int token) { · 15 unmodified lines
446421 // opcode1 encoding changes! highest and lowest bit gone.
447422 if (opcode1.e.v > 7) {
448423 tcc_error("opcode1 of instruction '%s' must be an immediate value between 0 and 7", get_tok_str(token, NULL));
449− return;
450424 }
451425 asm_emit_coprocessor_opcode(high_nibble, coprocessor, (opcode1.e.v << 1) | mrc, registers[0], registers[1], registers[2], opcode2.e.v, 1);
452426 break;
@@ -490,10 +464,8 @@ static void asm_block_data_transfer_opcode(TCCState *s1, int token) · 37 unmodified lines
490464 }
491465 if (nb_ops < 1) {
492466 expect("at least one operand");
493− return;
494467 } else if (ops[nb_ops - 1].type != OP_REGSET32) {
495468 expect("(last operand) register list");
496− return;
497469 }
498470
499471 // block data transfer: 1 0 0 P U S W L << 20 (general case):
@@ -683,12 +655,10 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 183 unmodified lines
683655 } else if (nb_ops == 3) {
684656 if (opcode_nos == 0xd || opcode_nos == 0xf || opcode_nos == 0xa || opcode_nos == 0xb || opcode_nos == 0x8 || opcode_nos == 0x9) { // mov, mvn, cmp, cmn, tst, teq
685657 tcc_error("'%s' cannot be used with three operands", get_tok_str(token, NULL));
686− return;
687658 }
688659 }
689660 if (nb_ops != 3) {
690661 expect("two or three operands");
691− return;
692662 } else {
693663 uint32_t opcode = 0;
694664 uint32_t immediate_value;
@@ -697,7 +667,6 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 2 unmodified lines
697667 if ((ops[0].type == OP_REG32 && ops[0].reg == 15) ||
698668 (ops[1].type == OP_REG32 && ops[1].reg == 15)) {
699669 tcc_error("Using the 'pc' register in data processing instructions that have a register-controlled shift is not implemented by ARM");
700− return;
701670 }
702671 }
703672
@@ -806,7 +775,6 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 102 unmodified lines
806775 if (half_immediate_rotation >= 16) {
807776 immediate_value = ops[2].e.v;
808777 tcc_error("immediate value 0x%X cannot be encoded into ARM immediate", (unsigned) immediate_value);
809− return;
810778 }
811779 operands |= immediate_value;
812780 operands |= half_immediate_rotation << 8;
@@ -846,12 +814,10 @@ static void asm_shift_opcode(TCCState *s1, int token) · 33 unmodified lines
846814 }
847815 if (nb_ops < 2) {
848816 expect("at least two operands");
849− return;
850817 }
851818
852819 if (ops[0].type != OP_REG32) {
853820 expect("(destination operand) register");
854− return;
855821 } else
856822 operands |= ENCODE_RD(ops[0].reg);
857823
@@ -876,7 +842,6 @@ static void asm_shift_opcode(TCCState *s1, int token) · 18 unmodified lines
876842 }
877843 if (nb_ops != 3) {
878844 expect("two or three operands");
879− return;
880845 }
881846
882847 switch (ARM_INSTRUCTION_GROUP(token)) {
@@ -896,7 +861,6 @@ static void asm_shift_opcode(TCCState *s1, int token) · 13 unmodified lines
896861 operands |= ENCODE_IMMEDIATE_FLAG;
897862 operands |= ops[1].e.v;
898863 tcc_error("Using an immediate value as the source operand is not possible with '%s' instruction on ARM", get_tok_str(token, NULL));
899− return;
900864 }
901865
902866 switch (ops[2].type) {
@@ -934,7 +898,6 @@ static void asm_shift_opcode(TCCState *s1, int token) · 31 unmodified lines
934898 break;
935899 default:
936900 expect("shift instruction");
937− return;
938901 }
939902 asm_emit_opcode(token, opcode | operands);
940903 }
@@ -963,7 +926,6 @@ static void asm_multiplication_opcode(TCCState *s1, int token) · 22 unmodified lines
963926 break;
964927 default:
965928 expect("at least three operands");
966− return;
967929 }
968930 nb_ops = 3;
969931 }
@@ -1037,7 +999,6 @@ static void asm_long_multiplication_opcode(TCCState *s1, int token) · 67 unmodified lines
1037999 }
10381000 if (nb_ops != 4) {
10391001 expect("four operands");
1040− return;
10411002 }
10421003
10431004 // long multiply (special case):
@@ -1117,12 +1078,10 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 73 unmodified lines
11171078 opcode |= ENCODE_RD(ops[0].reg);
11181079 else {
11191080 expect("(destination operand) register");
1120− return;
11211081 }
11221082 if (tok != ',')
11231083 expect("at least two arguments");
1124− else
1125− next(); // skip ','
1084+ next(); // skip ','
11261085
11271086 switch (ARM_INSTRUCTION_GROUP(token)) {
11281087 case TOK_ASM_strexbeq:
@@ -1130,7 +1089,6 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 1 unmodified line
11301089 parse_operand(s1, &strex_operand);
11311090 if (strex_operand.type != OP_REG32) {
11321091 expect("register");
1133− return;
11341092 }
11351093 if (tok != ',')
11361094 expect("at least three arguments");
@@ -1139,17 +1097,12 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 2 unmodified lines
11391097 break;
11401098 }
11411099
1142− if (tok != '[')
1143− expect("'['");
1144− else
1145− next(); // skip '['
1146−
1100+ skip('[');
11471101 parse_operand(s1, &ops[1]);
11481102 if (ops[1].type == OP_REG32)
11491103 opcode |= ENCODE_RN(ops[1].reg);
11501104 else {
11511105 expect("(first source operand) register");
1152− return;
11531106 }
11541107 if (tok == ']') {
11551108 next();
@@ -1166,7 +1119,6 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 10 unmodified lines
11661119 if (ops[2].type == OP_REG32) {
11671120 if (ops[2].reg == 15) {
11681121 tcc_error("Using 'pc' for register offset in '%s' is not implemented by ARM", get_tok_str(token, NULL));
1169− return;
11701122 }
11711123 if (tok == ',') {
11721124 next();
@@ -1182,10 +1134,7 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 9 unmodified lines
11821134 opcode |= 1 << 24; // add offset before transfer
11831135 }
11841136 if (!closed_bracket) {
1185− if (tok != ']')
1186− expect("']'");
1187− else
1188− next(); // skip ']'
1137+ skip(']');
11891138 opcode |= 1 << 24; // add offset before transfer
11901139 if (tok == '!') {
11911140 exclam = 1;
@@ -1257,14 +1206,11 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 65 unmodified lines
12571206 case TOK_ASM_strexeq:
12581207 if ((opcode & 0xFFF) || nb_shift) {
12591208 tcc_error("neither offset nor shift allowed with 'strex'");
1260− return;
12611209 } else if (opcode & ENCODE_IMMEDIATE_FLAG) { // if set, it means it's NOT immediate
12621210 tcc_error("offset not allowed with 'strex'");
1263− return;
12641211 }
12651212 if ((opcode & (1 << 24)) == 0) { // add offset after transfer
12661213 tcc_error("adding offset after transfer not allowed with 'strex'");
1267− return;
12681214 }
12691215
12701216 opcode |= 0xf90; // Used to mean: barrel shifter is enabled, barrel shift register is r15, mode is LSL
@@ -1277,14 +1223,11 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 6 unmodified lines
12771223 case TOK_ASM_ldrexeq:
12781224 if ((opcode & 0xFFF) || nb_shift) {
12791225 tcc_error("neither offset nor shift allowed with 'ldrex'");
1280− return;
12811226 } else if (opcode & ENCODE_IMMEDIATE_FLAG) { // if set, it means it's NOT immediate
12821227 tcc_error("offset not allowed with 'ldrex'");
1283− return;
12841228 }
12851229 if ((opcode & (1 << 24)) == 0) { // add offset after transfer
12861230 tcc_error("adding offset after transfer not allowed with 'ldrex'");
1287− return;
12881231 }
12891232 opcode |= 1 << 20; // L
12901233 opcode |= 0x00f;
@@ -1313,10 +1256,9 @@ static void asm_emit_coprocessor_data_transfer(uint32_t high_nibble, uint8_t cp_ · 22 unmodified lines
13131256 //assert(CRd < 16);
13141257 opcode |= ENCODE_RD(CRd);
13151258
1316− if (Rn->type != OP_REG32) {
1259+ if (Rn->type != OP_REG32)
13171260 expect("register");
1318− return;
1319− }
1261+
13201262 //assert(Rn->reg < 16);
13211263 opcode |= ENCODE_RN(Rn->reg);
13221264 if (preincrement)
@@ -1335,12 +1277,10 @@ static void asm_emit_coprocessor_data_transfer(uint32_t high_nibble, uint8_t cp_ · 12 unmodified lines
13351277 opcode |= 1 << 23; // up
13361278 if (v & 3) {
13371279 tcc_error("immediate offset must be a multiple of 4");
1338− return;
13391280 }
13401281 v >>= 2;
13411282 if (v > 255) {
13421283 tcc_error("immediate offset must be between -1020 and 1020");
1343− return;
13441284 }
13451285 opcode |= v;
13461286 } else if (offset->type == OP_REG32) {
@@ -1349,7 +1289,6 @@ static void asm_emit_coprocessor_data_transfer(uint32_t high_nibble, uint8_t cp_ · 2 unmodified lines
13491289 opcode |= ENCODE_IMMEDIATE_FLAG; /* if set, it means it's NOT immediate */
13501290 opcode |= offset->reg;
13511291 tcc_error("Using register offset to register address is not possible here");
1352− return;
13531292 } else if (offset->type == OP_VREG64) {
13541293 opcode |= 16;
13551294 opcode |= offset->reg;
@@ -1380,36 +1319,22 @@ static void asm_coprocessor_data_transfer_opcode(TCCState *s1, int token) · 24 unmodified lines
13801319 next();
13811320 } else {
13821321 expect("'c<number>'");
1383− return;
13841322 }
13851323
1386− if (tok == ',')
1387− next();
1388− else
1389− expect("','");
1324+ skip(',');
13901325
13911326 if (tok >= TOK_ASM_c0 && tok <= TOK_ASM_c15) {
13921327 coprocessor_destination_register = tok - TOK_ASM_c0;
13931328 next();
13941329 } else {
13951330 expect("'c<number>'");
1396− return;
13971331 }
13981332
1399− if (tok == ',')
1400− next();
1401− else
1402− expect("','");
1403−
1404− if (tok != '[')
1405− expect("'['");
1406− else
1407− next(); // skip '['
1408−
1333+ skip(',');
1334+ skip('[');
14091335 parse_operand(s1, &ops[1]);
14101336 if (ops[1].type != OP_REG32) {
14111337 expect("(first source operand) register");
1412− return;
14131338 }
14141339 if (tok == ']') {
14151340 next();
@@ -1426,11 +1351,9 @@ static void asm_coprocessor_data_transfer_opcode(TCCState *s1, int token) · 10 unmodified lines
14261351 if (ops[2].type == OP_REG32) {
14271352 if (ops[2].reg == 15) {
14281353 tcc_error("Using 'pc' for register offset in '%s' is not implemented by ARM", get_tok_str(token, NULL));
1429− return;
14301354 }
14311355 } else if (ops[2].type == OP_VREG64) {
14321356 tcc_error("'%s' does not support VFP register operand", get_tok_str(token, NULL));
1433− return;
14341357 }
14351358 } else {
14361359 // end of input expression in brackets--assume 0 offset
@@ -1439,10 +1362,7 @@ static void asm_coprocessor_data_transfer_opcode(TCCState *s1, int token) · 2 unmodified lines
14391362 preincrement = 1; // add offset before transfer
14401363 }
14411364 if (!closed_bracket) {
1442− if (tok != ']')
1443− expect("']'");
1444− else
1445− next(); // skip ']'
1365+ skip(']');
14461366 preincrement = 1; // add offset before transfer
14471367 if (tok == '!') {
14481368 exclam = 1;
@@ -1511,40 +1431,26 @@ static void asm_floating_point_single_data_transfer_opcode(TCCState *s1, int tok · 62 unmodified lines
15111431 next();
15121432 } else {
15131433 expect("floating point register");
1514− return;
15151434 }
15161435
1517− if (tok == ',')
1518− next();
1519− else
1520− expect("','");
1521−
1522− if (tok != '[')
1523− expect("'['");
1524− else
1525− next(); // skip '['
1526−
1436+ skip(',');
1437+ skip('[');
15271438 parse_operand(s1, &ops[1]);
15281439 if (ops[1].type != OP_REG32) {
15291440 expect("(first source operand) register");
1530− return;
15311441 }
15321442 if (tok == ',') {
15331443 next(); // skip ','
15341444 parse_operand(s1, &ops[2]);
15351445 if (ops[2].type != OP_IM8 && ops[2].type != OP_IM8N) {
15361446 expect("immediate offset");
1537− return;
15381447 }
15391448 } else {
15401449 // end of input expression in brackets--assume 0 offset
15411450 ops[2].type = OP_IM8;
15421451 ops[2].e.v = 0;
15431452 }
1544− if (tok != ']')
1545− expect("']'");
1546− else
1547− next(); // skip ']'
1453+ skip(']');
15481454
15491455 switch (ARM_INSTRUCTION_GROUP(token)) {
15501456 case TOK_ASM_vldreq:
@@ -1583,19 +1489,10 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *s1, int toke · 32 unmodified lines
15831489 op0_exclam = 1;
15841490 next(); // skip '!'
15851491 }
1586− if (tok == ',')
1587− next(); // skip comma
1588− else {
1589− expect("','");
1590− return;
1591− }
1492+ skip(',');
15921493 }
15931494
1594− if (tok != '{') {
1595− expect("'{'");
1596− return;
1597− }
1598− next(); // skip '{'
1495+ skip('{');
15991496 first_regset_register = asm_parse_vfp_regvar(tok, 1);
16001497 if ((first_regset_register = asm_parse_vfp_regvar(tok, 1)) != -1) {
16011498 coprocessor = CP_DOUBLE_PRECISION_FLOAT;
@@ -1605,7 +1502,6 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *s1, int toke · 3 unmodified lines
16051502 next();
16061503 } else {
16071504 expect("floating-point register");
1608− return;
16091505 }
16101506
16111507 if (tok == '-') {
@@ -1614,21 +1510,14 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *s1, int toke · 2 unmodified lines
16141510 next();
16151511 else {
16161512 expect("floating-point register");
1617− return;
16181513 }
16191514 } else
16201515 last_regset_register = first_regset_register;
16211516
16221517 if (last_regset_register < first_regset_register) {
16231518 tcc_error("registers will be processed in ascending order by hardware--but are not specified in ascending order here");
1624− return;
1625− }
1626− if (tok != '}') {
1627− expect("'}'");
1628− return;
16291519 }
1630− next(); // skip '}'
1631−
1520+ skip('}');
16321521 // Note: 0 (one down) is not implemented by us regardless.
16331522 regset_item_count = last_regset_register - first_regset_register + 1;
16341523 if (coprocessor == CP_DOUBLE_PRECISION_FLOAT)
@@ -1659,7 +1548,6 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *s1, int toke · 24 unmodified lines
16591548 break;
16601549 default:
16611550 expect("floating point block data transfer instruction");
1662− return;
16631551 }
16641552 if (ops[0].type != OP_REG32)
16651553 expect("(first operand) register");
@@ -1713,7 +1601,6 @@ static uint32_t vmov_parse_immediate_value() { · 47 unmodified lines
17131601
17141602 if (tok != TOK_PPNUM) {
17151603 expect("immediate value");
1716− return 0;
17171604 }
17181605 p = tokc.str.data;
17191606 errno = 0;
@@ -1721,7 +1608,6 @@ static uint32_t vmov_parse_immediate_value() { · 1 unmodified line
17211608
17221609 if (errno || integral_value >= 32) {
17231610 tcc_error("invalid floating-point immediate value");
1724− return 0;
17251611 }
17261612
17271613 value = (uint32_t) integral_value * VMOV_ONE;
@@ -1754,7 +1640,6 @@ static uint8_t vmov_encode_immediate_value(uint32_t value) · 26 unmodified lines
17541640 }
17551641 if (r == -1 || value < beginning || value > end) {
17561642 tcc_error("invalid decimal number for vmov: %d", value);
1757− return 0;
17581643 }
17591644 n = vmov_linear_approx_index(beginning, end, value);
17601645 return n | (((3 - r) & 0x7) << 4);
@@ -1788,7 +1673,6 @@ static void asm_floating_point_immediate_data_processing_opcode_tail(TCCState *s · 27 unmodified lines
17881673 operands[1] = 5;
17891674 if (immediate_value) {
17901675 expect("Immediate value 0");
1791− return;
17921676 }
17931677 break;
17941678 case TOK_ASM_vcmpeeq_f32:
@@ -1797,7 +1681,6 @@ static void asm_floating_point_immediate_data_processing_opcode_tail(TCCState *s · 2 unmodified lines
17971681 operands[1] = 5;
17981682 if (immediate_value) {
17991683 expect("Immediate value 0");
1800− return;
18011684 }
18021685 break;
18031686 case TOK_ASM_vmoveq_f32:
@@ -1813,7 +1696,6 @@ static void asm_floating_point_immediate_data_processing_opcode_tail(TCCState *s · 9 unmodified lines
18131696 break;
18141697 default:
18151698 expect("known floating point with immediate instruction");
1816− return;
18171699 }
18181700
18191701 if (coprocessor == CP_SINGLE_PRECISION_FLOAT) {
@@ -1833,7 +1715,6 @@ static void asm_floating_point_reg_arm_reg_transfer_opcode_tail(TCCState *s1, in · 13 unmodified lines
18331715 // "vmov.f32 r2, s3" or "vmov.f32 s3, r2"
18341716 if (nb_ops != 2 || nb_arm_regs != 1) {
18351717 tcc_error("vmov.f32 only implemented for one VFP register operand and one ARM register operands");
1836− return;
18371718 }
18381719 if (ops[0].type != OP_REG32) { // determine mode: load or store
18391720 // need to swap operands 0 and 1
@@ -1860,7 +1741,6 @@ static void asm_floating_point_reg_arm_reg_transfer_opcode_tail(TCCState *s1, in · 20 unmodified lines
18601741 case CP_DOUBLE_PRECISION_FLOAT:
18611742 if (nb_ops != 3 || nb_arm_regs != 2) {
18621743 tcc_error("vmov.f32 only implemented for one VFP register operand and two ARM register operands");
1863− return;
18641744 }
18651745 // Determine whether it's a store into a VFP register (vmov "d1, r2, r3") rather than "vmov r2, r3, d1"
18661746 if (ops[0].type == OP_VREG64) {
@@ -1873,11 +1753,9 @@ static void asm_floating_point_reg_arm_reg_transfer_opcode_tail(TCCState *s1, in · 6 unmodified lines
18731753 memcpy(&ops[2], &temp, sizeof(ops[2]));
18741754 } else {
18751755 tcc_error("vmov.f64 only implemented for one VFP register operand and two ARM register operands");
1876− return;
18771756 }
18781757 } else if (ops[0].type != OP_REG32 || ops[1].type != OP_REG32 || ops[2].type != OP_VREG64) {
18791758 tcc_error("vmov.f64 only implemented for one VFP register operand and two ARM register operands");
1880− return;
18811759 } else {
18821760 opcode1 |= 1;
18831761 }
@@ -1915,7 +1793,6 @@ static void asm_floating_point_vcvt_data_processing_opcode(TCCState *s1, int tok · 31 unmodified lines
19151793 break;
19161794 default:
19171795 tcc_error("Unknown coprocessor for instruction '%s'", get_tok_str(token, NULL));
1918− return;
19191796 }
19201797
19211798 parse_operand(s1, &ops[0]);
@@ -1942,10 +1819,7 @@ static void asm_floating_point_vcvt_data_processing_opcode(TCCState *s1, int tok · 20 unmodified lines
19421819 break;
19431820 }
19441821
1945− if (tok == ',')
1946− next();
1947− else
1948− expect("','");
1822+ skip(',');
19491823 parse_operand(s1, &ops[2]);
19501824
19511825 switch (ARM_INSTRUCTION_GROUP(token)) {
@@ -1977,7 +1851,6 @@ static void asm_floating_point_vcvt_data_processing_opcode(TCCState *s1, int tok · 25 unmodified lines
19771851 if (ops[0].type == OP_VREG64 && ops[2].type == OP_VREG32) {
19781852 } else {
19791853 expect("d<number>, s<number>");
1980− return;
19811854 }
19821855 break;
19831856 default:
@@ -1985,13 +1858,11 @@ static void asm_floating_point_vcvt_data_processing_opcode(TCCState *s1, int tok · 1 unmodified line
19851858 if (ops[0].type == OP_VREG32 && ops[2].type == OP_VREG32) {
19861859 } else {
19871860 expect("s<number>, s<number>");
1988− return;
19891861 }
19901862 } else if (coprocessor == CP_DOUBLE_PRECISION_FLOAT) {
19911863 if (ops[0].type == OP_VREG32 && ops[2].type == OP_VREG64) {
19921864 } else {
19931865 expect("s<number>, d<number>");
1994− return;
19951866 }
19961867 }
19971868 }
@@ -2074,16 +1945,13 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 76 unmodified lines
20741945 } else if (ops[nb_ops].type == OP_VREG32) {
20751946 if (coprocessor != CP_SINGLE_PRECISION_FLOAT) {
20761947 expect("'s<number>'");
2077− return;
20781948 }
20791949 } else if (ops[nb_ops].type == OP_VREG64) {
20801950 if (coprocessor != CP_DOUBLE_PRECISION_FLOAT) {
20811951 expect("'d<number>'");
2082− return;
20831952 }
20841953 } else {
20851954 expect("floating point register");
2086− return;
20871955 }
20881956 ++nb_ops;
20891957 if (tok == ',')
@@ -2100,7 +1968,6 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 10 unmodified lines
21001968 }
21011969 if (nb_ops < 3) {
21021970 tcc_error("Not enough operands for '%s' (%u)", get_tok_str(token, NULL), nb_ops);
2103− return;
21041971 }
21051972 }
21061973
@@ -2199,7 +2066,6 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 92 unmodified lines
21992066 break;
22002067 default:
22012068 expect("known floating point instruction");
2202− return;
22032069 }
22042070
22052071 if (coprocessor == CP_SINGLE_PRECISION_FLOAT) {
@@ -2256,46 +2122,34 @@ static void asm_floating_point_status_register_opcode(TCCState* s1, int token) · 50 unmodified lines
22562122 parse_operand(s1, &arm_operand);
22572123 if (arm_operand.type == OP_REG32 && arm_operand.reg == 15) {
22582124 tcc_error("'%s' does not support 'pc' as operand", get_tok_str(token, NULL));
2259− return;
22602125 }
22612126 }
22622127
2263− if (tok != ',')
2264− expect("','");
2265− else
2266− next(); // skip ','
2128+ skip(',');
22672129 vfp_sys_reg = asm_parse_vfp_status_regvar(tok);
22682130 next(); // skip vfp sys reg
22692131 if (arm_operand.type == OP_REG32 && arm_operand.reg == 15 && vfp_sys_reg != 1) {
22702132 tcc_error("'%s' only supports the variant 'vmrs apsr_nzcv, fpscr' here", get_tok_str(token, NULL));
2271− return;
22722133 }
22732134 break;
22742135 case TOK_ASM_vmsreq:
22752136 opcode = 0xe;
22762137 vfp_sys_reg = asm_parse_vfp_status_regvar(tok);
22772138 next(); // skip vfp sys reg
2278− if (tok != ',')
2279− expect("','");
2280− else
2281− next(); // skip ','
2139+ skip(',');
22822140 parse_operand(s1, &arm_operand);
22832141 if (arm_operand.type == OP_REG32 && arm_operand.reg == 15) {
22842142 tcc_error("'%s' does not support 'pc' as operand", get_tok_str(token, NULL));
2285− return;
22862143 }
22872144 break;
22882145 default:
22892146 expect("floating point status register instruction");
2290− return;
22912147 }
22922148 if (vfp_sys_reg == -1) {
22932149 expect("VFP system register");
2294− return;
22952150 }
22962151 if (arm_operand.type != OP_REG32) {
22972152 expect("ARM register");
2298− return;
22992153 }
23002154 asm_emit_coprocessor_opcode(condition_code_of_token(token), coprocessor, opcode, arm_operand.reg, vfp_sys_reg, 0x10, 0, 0);
23012155 }
@@ -2327,24 +2181,17 @@ static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token) · 25 unmodified lines
23272181 opcode |= ENCODE_RD(ops[0].reg);
23282182 else {
23292183 expect("(destination operand) register");
2330− return;
23312184 }
23322185 if (tok != ',')
23332186 expect("at least two arguments");
23342187 else
23352188 next(); // skip ','
2336−
2337− if (tok != '[')
2338− expect("'['");
2339− else
2340− next(); // skip '['
2341−
2189+ skip('[');
23422190 parse_operand(s1, &ops[1]);
23432191 if (ops[1].type == OP_REG32)
23442192 opcode |= ENCODE_RN(ops[1].reg);
23452193 else {
23462194 expect("(first source operand) register");
2347− return;
23482195 }
23492196 if (tok == ']') {
23502197 next();
@@ -2365,10 +2212,7 @@ static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token) · 14 unmodified lines
23652212 opcode |= 1 << 24; // add offset before transfer
23662213 }
23672214 if (!closed_bracket) {
2368− if (tok != ']')
2369− expect("']'");
2370− else
2371− next(); // skip ']'
2215+ skip(']');
23722216 opcode |= 1 << 24; // add offset before transfer
23732217 if (tok == '!') {
23742218 exclam = 1;
@@ -2379,7 +2223,6 @@ static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token) · 4 unmodified lines
23792223 if (exclam) {
23802224 if ((opcode & (1 << 24)) == 0) {
23812225 tcc_error("result of '%s' would be unpredictable here", get_tok_str(token, NULL));
2382− return;
23832226 }
23842227 opcode |= 1 << 21; // write offset back into register
23852228 }
@@ -2465,7 +2308,6 @@ static void asm_branch_opcode(TCCState *s1, int token) · 79 unmodified lines
24652308 esym = elfsym(e.sym);
24662309 if (!esym || esym->st_shndx != cur_text_section->sh_num) {
24672310 tcc_error("invalid branch target");
2468− return;
24692311 }
24702312 jmp_disp = encbranchoffset(ind, e.v + esym->st_value, 1);
24712313 break;
@@ -2518,7 +2360,6 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 46 unmodified lines
25182360 return;
25192361 default:
25202362 expect("instruction");
2521− return;
25222363 }
25232364 }
25242365
@@ -2740,7 +2581,6 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 215 unmodified lines
27402581 ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
27412582 {
27422583 int r, reg, size, val;
2743− char buf[64];
27442584
27452585 r = sv->r;
27462586 if ((r & VT_VALMASK) == VT_CONST) {
@@ -2767,19 +2607,16 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier) · 20 unmodified lines
27672607 val = sv->c.i;
27682608 if (modifier == 'n')
27692609 val = -val;
2770− snprintf(buf, sizeof(buf), "%d", (int) sv->c.i);
2771− cstr_cat(add_str, buf, -1);
2610+ cstr_printf(add_str, "%d", (int) sv->c.i);
27722611 no_offset:;
27732612 } else if ((r & VT_VALMASK) == VT_LOCAL) {
2774− snprintf(buf, sizeof(buf), "[fp,#%d]", (int) sv->c.i);
2775− cstr_cat(add_str, buf, -1);
2613+ cstr_printf(add_str, "[fp,#%d]", (int) sv->c.i);
27762614 } else if (r & VT_LVAL) {
27772615 reg = r & VT_VALMASK;
27782616 if (reg >= VT_CONST)
27792617 tcc_internal_error("");
2780− snprintf(buf, sizeof(buf), "[%s]",
2618+ cstr_printf(add_str, "[%s]",
27812619 get_tok_str(TOK_ASM_r0 + reg, NULL));
2782− cstr_cat(add_str, buf, -1);
27832620 } else {
27842621 /* register case */
27852622 reg = r & VT_VALMASK;
@@ -2808,8 +2645,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier) · 22 unmodified lines
28082645 reg = TOK_ASM_r0 + reg;
28092646 break;
28102647 }
2811− snprintf(buf, sizeof(buf), "%s", get_tok_str(reg, NULL));
2812− cstr_cat(add_str, buf, -1);
2648+ cstr_printf(add_str, "%s", get_tok_str(reg, NULL));
28132649 }
28142650 }
28152651
@@ -2928,7 +2764,6 @@ static inline int constraint_priority(const char *str) · 112 unmodified lines
29282764 break;
29292765 default:
29302766 tcc_error("unknown constraint '%c'", c);
2931− pr = 0;
29322767 }
29332768 if (pr > priority)
29342769 priority = pr;
arm-link.c+3−3
@@ -30,7 +30,7 @@ enum float_abi { · 29 unmodified lines
3030 #ifdef NEED_RELOC_TYPE
3131 /* Returns 1 for a code relocation, 0 for a data relocation. For unknown
3232 relocations, returns -1. */
33−int code_reloc (int reloc_type)
33+ST_FUNC int code_reloc (int reloc_type)
3434 {
3535 switch (reloc_type) {
3636 case R_ARM_MOVT_ABS:
@@ -68,7 +68,7 @@ int code_reloc (int reloc_type) · 31 unmodified lines
6868 /* Returns an enumerator to describe whether and when the relocation needs a
6969 GOT and/or PLT entry to be created. See tcc.h for a description of the
7070 different values. */
71−int gotplt_entry_type (int reloc_type)
71+ST_FUNC int gotplt_entry_type (int reloc_type)
7272 {
7373 switch (reloc_type) {
7474 case R_ARM_NONE:
@@ -179,7 +179,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 104 unmodified lines
179179 #endif
180180 #endif
181181
182−void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
182+ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
183183 {
184184 ElfW(Sym) *sym;
185185 int sym_index, esym_index;
arm64-link.c+3−3
@@ -24,7 +24,7 @@ · 23 unmodified lines
2424 #ifdef NEED_RELOC_TYPE
2525 /* Returns 1 for a code relocation, 0 for a data relocation. For unknown
2626 relocations, returns -1. */
27−int code_reloc (int reloc_type)
27+ST_FUNC int code_reloc (int reloc_type)
2828 {
2929 switch (reloc_type) {
3030 case R_AARCH64_ABS32:
@@ -58,7 +58,7 @@ int code_reloc (int reloc_type) · 27 unmodified lines
5858 /* Returns an enumerator to describe whether and when the relocation needs a
5959 GOT and/or PLT entry to be created. See tcc.h for a description of the
6060 different values. */
61−int gotplt_entry_type (int reloc_type)
61+ST_FUNC int gotplt_entry_type (int reloc_type)
6262 {
6363 switch (reloc_type) {
6464 case R_AARCH64_PREL32:
@@ -168,7 +168,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 103 unmodified lines
168168 #endif
169169 #endif
170170
171−void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
171+ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
172172 {
173173 int sym_index = ELFW(R_SYM)(rel->r_info), esym_index;
174174 #ifdef DEBUG_RELOC
c67-link.c+3−3
@@ -24,7 +24,7 @@ · 23 unmodified lines
2424
2525 /* Returns 1 for a code relocation, 0 for a data relocation. For unknown
2626 relocations, returns -1. */
27−int code_reloc (int reloc_type)
27+ST_FUNC int code_reloc (int reloc_type)
2828 {
2929 switch (reloc_type) {
3030 case R_C60_32:
@@ -45,7 +45,7 @@ int code_reloc (int reloc_type) · 14 unmodified lines
4545 /* Returns an enumerator to describe whether and when the relocation needs a
4646 GOT and/or PLT entry to be created. See tcc.h for a description of the
4747 different values. */
48−int gotplt_entry_type (int reloc_type)
48+ST_FUNC int gotplt_entry_type (int reloc_type)
4949 {
5050 switch (reloc_type) {
5151 case R_C60_32:
@@ -91,7 +91,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 39 unmodified lines
9191 }
9292 }
9393
94−void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
94+ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
9595 {
9696 switch(type) {
9797 case R_C60_32:
i386-asm.c+6−19
@@ -143,10 +143,12 @@ enum { · 142 unmodified lines
143143 # define TREG_XAX TREG_RAX
144144 # define TREG_XCX TREG_RCX
145145 # define TREG_XDX TREG_RDX
146+# define TOK_ASM_xax TOK_ASM_rax
146147 #else
147148 # define TREG_XAX TREG_EAX
148149 # define TREG_XCX TREG_ECX
149150 # define TREG_XDX TREG_EDX
151+# define TOK_ASM_xax TOK_ASM_eax
150152 #endif
151153
152154 typedef struct ASMInstr {
@@ -1505,7 +1507,6 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 1352 unmodified lines
15051507 SValue *sv, int modifier)
15061508 {
15071509 int r, reg, size, val;
1508− char buf[64];
15091510
15101511 r = sv->r;
15111512 if ((r & VT_VALMASK) == VT_CONST) {
@@ -1532,32 +1533,19 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 20 unmodified lines
15321533 val = sv->c.i;
15331534 if (modifier == 'n')
15341535 val = -val;
1535− snprintf(buf, sizeof(buf), "%d", (int)sv->c.i);
1536− cstr_cat(add_str, buf, -1);
1536+ cstr_printf(add_str, "%d", (int)sv->c.i);
15371537 no_offset:;
15381538 #ifdef TCC_TARGET_X86_64
15391539 if (r & VT_LVAL)
15401540 cstr_cat(add_str, "(%rip)", -1);
15411541 #endif
15421542 } else if ((r & VT_VALMASK) == VT_LOCAL) {
1543−#ifdef TCC_TARGET_X86_64
1544− snprintf(buf, sizeof(buf), "%d(%%rbp)", (int)sv->c.i);
1545−#else
1546− snprintf(buf, sizeof(buf), "%d(%%ebp)", (int)sv->c.i);
1547−#endif
1548− cstr_cat(add_str, buf, -1);
1543+ cstr_printf(add_str, "%d(%%%s)", (int)sv->c.i, get_tok_str(TOK_ASM_xax + 5, NULL));
15491544 } else if (r & VT_LVAL) {
15501545 reg = r & VT_VALMASK;
15511546 if (reg >= VT_CONST)
15521547 tcc_internal_error("");
1553− snprintf(buf, sizeof(buf), "(%%%s)",
1554−#ifdef TCC_TARGET_X86_64
1555− get_tok_str(TOK_ASM_rax + reg, NULL)
1556−#else
1557− get_tok_str(TOK_ASM_eax + reg, NULL)
1558−#endif
1559− );
1560− cstr_cat(add_str, buf, -1);
1548+ cstr_printf(add_str, "(%%%s)", get_tok_str(TOK_ASM_xax + reg, NULL));
15611549 } else {
15621550 /* register case */
15631551 reg = r & VT_VALMASK;
@@ -1617,8 +1605,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 53 unmodified lines
16171605 break;
16181606 #endif
16191607 }
1620− snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
1621− cstr_cat(add_str, buf, -1);
1608+ cstr_printf(add_str, "%%%s", get_tok_str(reg, NULL));
16221609 }
16231610 }
16241611
i386-gen.c+8−24
@@ -410,9 +410,7 @@ ST_FUNC void gfunc_call(int nb_args) · 409 unmodified lines
410410 {
411411 int size, align, r, args_size, i, func_call;
412412 Sym *func_sym;
413− // Look ahead to the function on the stack to get the function call type
414− int func_call2 = ((vtop - nb_args)->type.ref)->f.func_call;
415−
413+
416414 #ifdef CONFIG_TCC_BCHECK
417415 if (tcc_state->do_bounds_check)
418416 gbound_args(nb_args);
@@ -420,12 +418,6 @@ ST_FUNC void gfunc_call(int nb_args) · 1 unmodified line
420418
421419 args_size = 0;
422420 for(i = 0;i < nb_args; i++) {
423− if (func_call2 == FUNC_THISCALL && i == (nb_args - 1)) {
424− // If thiscall, zap the last push, as it is `this`. Instead, mov into ecx
425− size = 0;
426− load(get_reg(RC_ECX), vtop);
427− }
428− else
429421 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
430422 size = type_size(&vtop->type, &align);
431423 /* align to stack align size */
@@ -486,12 +478,15 @@ ST_FUNC void gfunc_call(int nb_args) · 54 unmodified lines
486478 func_call = func_sym->f.func_call;
487479 /* fast call case */
488480 if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) ||
489− func_call == FUNC_FASTCALLW) {
481+ func_call == FUNC_FASTCALLW || func_call == FUNC_THISCALL) {
490482 int fastcall_nb_regs;
491483 const uint8_t *fastcall_regs_ptr;
492484 if (func_call == FUNC_FASTCALLW) {
493485 fastcall_regs_ptr = fastcallw_regs;
494486 fastcall_nb_regs = 2;
487+ } else if (func_call == FUNC_THISCALL) {
488+ fastcall_regs_ptr = fastcallw_regs;
489+ fastcall_nb_regs = 1;
495490 } else {
496491 fastcall_regs_ptr = fastcall_regs;
497492 fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
@@ -531,7 +526,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 33 unmodified lines
531526 const uint8_t *fastcall_regs_ptr;
532527 Sym *sym;
533528 CType *type;
534− int thiscall_nb_regs;
535529
536530 sym = func_type->ref;
537531 func_call = sym->f.func_call;
@@ -545,15 +539,13 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 7 unmodified lines
545539 } else if (func_call == FUNC_FASTCALLW) {
546540 fastcall_nb_regs = 2;
547541 fastcall_regs_ptr = fastcallw_regs;
542+ } else if (func_call == FUNC_THISCALL) {
543+ fastcall_nb_regs = 1;
544+ fastcall_regs_ptr = fastcallw_regs;
548545 } else {
549546 fastcall_nb_regs = 0;
550547 fastcall_regs_ptr = NULL;
551548 }
552−
553− if (func_call == FUNC_THISCALL) {
554− thiscall_nb_regs = 1;
555− }
556−
557549 param_index = 0;
558550
559551 ind += FUNC_PROLOG_SIZE;
@@ -589,14 +581,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 29 unmodified lines
589581 o(0x89); /* movl */
590582 gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc);
591583 param_addr = loc;
592− }
593− else if(param_index < thiscall_nb_regs) {
594− /* Why ? */
595− /* save THISCALL register; ECX */
596− loc -= 4;
597− o(0x89); /* movl */
598− gen_modrm(TREG_ECX, VT_LOCAL, NULL, loc);
599− param_addr = loc;
600584 } else {
601585 param_addr = addr;
602586 addr += size;
i386-link.c+3−3
@@ -25,7 +25,7 @@ · 24 unmodified lines
2525 #ifdef NEED_RELOC_TYPE
2626 /* Returns 1 for a code relocation, 0 for a data relocation. For unknown
2727 relocations, returns -1. */
28−int code_reloc (int reloc_type)
28+ST_FUNC int code_reloc (int reloc_type)
2929 {
3030 switch (reloc_type) {
3131 case R_386_RELATIVE:
@@ -55,7 +55,7 @@ int code_reloc (int reloc_type) · 23 unmodified lines
5555 /* Returns an enumerator to describe whether and when the relocation needs a
5656 GOT and/or PLT entry to be created. See tcc.h for a description of the
5757 different values. */
58−int gotplt_entry_type (int reloc_type)
58+ST_FUNC int gotplt_entry_type (int reloc_type)
5959 {
6060 switch (reloc_type) {
6161 case R_386_RELATIVE:
@@ -171,7 +171,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 109 unmodified lines
171171 #endif
172172 #endif
173173
174−void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
174+ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
175175 {
176176 int sym_index, esym_index;
177177
libtcc.c+27−17
@@ -201,7 +201,8 @@ ST_FUNC char *tcc_load_text(int fd) · 200 unmodified lines
201201 {
202202 int len = lseek(fd, 0, SEEK_END);
203203 char *buf = load_data(fd, 0, len + 1);
204− buf[len] = 0;
204+ if (buf)
205+ buf[len] = 0;
205206 return buf;
206207 }
207208
@@ -336,7 +337,8 @@ PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line) · 128 unmodified lines
336337 {
337338 int ofs;
338339 mem_debug_header_t *header;
339−
340+ if (!size)
341+ return NULL;
340342 header = tcc_malloc(sizeof(mem_debug_header_t) + size);
341343 header->magic1 = MEM_DEBUG_MAGIC1;
342344 header->magic2 = MEM_DEBUG_MAGIC2;
@@ -346,7 +348,6 @@ PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line) · 3 unmodified lines
346348 ofs = strlen(file) - MEM_DEBUG_FILE_LEN;
347349 strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN);
348350 header->file_name[MEM_DEBUG_FILE_LEN] = 0;
349−
350351 WAIT_SEM(&mem_sem);
351352 header->next = mem_debug_chain;
352353 header->prev = NULL;
@@ -357,7 +358,6 @@ PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line) · 4 unmodified lines
357358 if (mem_cur_size > mem_max_size)
358359 mem_max_size = mem_cur_size;
359360 POST_SEM(&mem_sem);
360−
361361 return MEM_USER_PTR(header);
362362 }
363363
@@ -367,7 +367,6 @@ PUB_FUNC void tcc_free_debug(void *ptr) · 3 unmodified lines
367367 if (!ptr)
368368 return;
369369 header = malloc_check(ptr, "tcc_free");
370−
371370 WAIT_SEM(&mem_sem);
372371 mem_cur_size -= header->size;
373372 header->size = (unsigned)-1;
@@ -385,7 +384,8 @@ PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line) · 11 unmodified lines
385384 {
386385 void *ptr;
387386 ptr = tcc_malloc_debug(size,file,line);
388− memset(ptr, 0, size);
387+ if (size)
388+ memset(ptr, 0, size);
389389 return ptr;
390390 }
391391
@@ -393,10 +393,14 @@ PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file · 1 unmodified line
393393 {
394394 mem_debug_header_t *header;
395395 int mem_debug_chain_update = 0;
396+
396397 if (!ptr)
397398 return tcc_malloc_debug(size, file, line);
399+ if (!size) {
400+ tcc_free_debug(ptr);
401+ return NULL;
402+ }
398403 header = malloc_check(ptr, "tcc_realloc");
399−
400404 WAIT_SEM(&mem_sem);
401405 mem_cur_size -= header->size;
402406 mem_debug_chain_update = (header == mem_debug_chain);
@@ -413,7 +417,6 @@ PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file · 10 unmodified lines
413417 if (mem_cur_size > mem_max_size)
414418 mem_max_size = mem_cur_size;
415419 POST_SEM(&mem_sem);
416−
417420 return MEM_USER_PTR(header);
418421 }
419422
@@ -441,6 +444,7 @@ PUB_FUNC void tcc_memcheck(int d) · 21 unmodified lines
441444 }
442445 fflush(stderr);
443446 mem_cur_size = 0;
447+ mem_max_size = 0;
444448 mem_debug_chain = NULL;
445449 #if MEM_DEBUG-0 == 2
446450 exit(2);
@@ -1425,24 +1429,24 @@ static int tcc_set_linker(TCCState *s, const char *option) · 978 unmodified lines
14251429 s->pe_stack_size = strtoul(p, &end, 10);
14261430 } else if (link_option(option, "subsystem=", &p)) {
14271431 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1428− if (!strcmp(p, "native")) {
1432+ if (strstart("native", &p)) {
14291433 s->pe_subsystem = 1;
1430− } else if (!strcmp(p, "console")) {
1434+ } else if (strstart("console", &p)) {
14311435 s->pe_subsystem = 3;
1432− } else if (!strcmp(p, "gui") || !strcmp(p, "windows")) {
1436+ } else if (strstart("gui", &p) || strstart("windows", &p)) {
14331437 s->pe_subsystem = 2;
1434− } else if (!strcmp(p, "posix")) {
1438+ } else if (strstart("posix", &p)) {
14351439 s->pe_subsystem = 7;
1436− } else if (!strcmp(p, "efiapp")) {
1440+ } else if (strstart("efiapp", &p)) {
14371441 s->pe_subsystem = 10;
1438− } else if (!strcmp(p, "efiboot")) {
1442+ } else if (strstart("efiboot", &p)) {
14391443 s->pe_subsystem = 11;
1440− } else if (!strcmp(p, "efiruntime")) {
1444+ } else if (strstart("efiruntime", &p)) {
14411445 s->pe_subsystem = 12;
1442− } else if (!strcmp(p, "efirom")) {
1446+ } else if (strstart("efirom", &p)) {
14431447 s->pe_subsystem = 13;
14441448 #elif defined(TCC_TARGET_ARM)
1445− if (!strcmp(p, "wince")) {
1449+ if (strstart("wince", &p)) {
14461450 s->pe_subsystem = 9;
14471451 #endif
14481452 } else
@@ -2211,3 +2215,9 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time) · 762 unmodified lines
22112215 fprintf(stderr, " %d max (bytes)\n", mem_max_size);
22122216 #endif
22132217 }
2218+
2219+#if ONE_SOURCE
2220+# undef malloc
2221+# undef realloc
2222+# undef free
2223+#endif
riscv64-asm.c+28−108
@@ -48,6 +48,10 @@ typedef struct Operand { · 47 unmodified lines
4848 };
4949 } Operand;
5050
51+static const Operand zero = { OP_REG, { 0 }};
52+static const Operand ra = { OP_REG, { 1 }};
53+static const Operand zimm = { OP_IM12S };
54+
5155 static void asm_binary_opcode(TCCState* s1, int token);
5256 ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str);
5357 ST_FUNC void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
@@ -128,9 +132,6 @@ static void asm_emit_opcode(uint32_t opcode) { · 74 unmodified lines
128132
129133 static void asm_nullary_opcode(TCCState *s1, int token)
130134 {
131− static const Operand nil = {.type = OP_REG};
132− static const Operand zimm = {.type = OP_IM12S};
133−
134135 switch (token) {
135136 // Sync instructions
136137
@@ -150,7 +151,7 @@ static void asm_nullary_opcode(TCCState *s1, int token) · 13 unmodified lines
150151 // Other
151152
152153 case TOK_ASM_nop:
153− asm_emit_i(token, (4 << 2) | 3, &nil, &nil, &zimm);
154+ asm_emit_i(token, (4 << 2) | 3, &zero, &zero, &zimm);
154155 return;
155156
156157 case TOK_ASM_wfi:
@@ -165,10 +166,10 @@ static void asm_nullary_opcode(TCCState *s1, int token) · 8 unmodified lines
165166
166167 /* C extension */
167168 case TOK_ASM_c_ebreak:
168− asm_emit_cr(token, 2 | (9 << 12), &nil, &nil);
169+ asm_emit_cr(token, 2 | (9 << 12), &zero, &zero);
169170 return;
170171 case TOK_ASM_c_nop:
171− asm_emit_ci(token, 1, &nil, &zimm);
172+ asm_emit_ci(token, 1, &zero, &zimm);
172173 return;
173174
174175 default:
@@ -266,33 +267,24 @@ static void parse_jump_offset_operand(TCCState *s1, Operand *op){ · 91 unmodified lines
266267 static void parse_operands(TCCState *s1, Operand* ops, int count){
267268 int i;
268269 for (i = 0; i < count; i++) {
269− if ( i != 0 ) {
270− if ( tok == ',')
271− next();
272− else
273− expect("','");
274− }
270+ if ( i != 0 )
271+ skip(',');
275272 parse_operand(s1, &ops[i]);
276273 }
277274 }
278275
279276 /* parse `X, imm(Y)` to {X, Y, imm} operands */
280277 static void parse_mem_access_operands(TCCState *s1, Operand* ops){
281− static const Operand zimm = {.type = OP_IM12S};
282278
283279 Operand op;
284280
285281 parse_operand(s1, &ops[0]);
286− if ( tok == ',')
287− next();
288− else
289− expect("','");
290−
282+ skip(',');
291283 if ( tok == '(') {
292284 /* `X, (Y)` case*/
293285 next();
294286 parse_operand(s1, &ops[1]);
295− if ( tok == ')') next(); else expect("')'");
287+ skip(')');
296288 ops[2] = zimm;
297289 } else {
298290 parse_operand(s1, &ops[2]);
@@ -300,7 +292,7 @@ static void parse_mem_access_operands(TCCState *s1, Operand* ops){ · 1 unmodified line
300292 /* `X, imm(Y)` case*/
301293 next();
302294 parse_operand(s1, &ops[1]);
303− if ( tok == ')') next(); else expect("')'");
295+ skip(')');
304296 } else {
305297 /* `X, Y` case*/
306298 /* we parsed Y thinking it was imm, swap and default imm to zero */
@@ -314,8 +306,6 @@ static void parse_mem_access_operands(TCCState *s1, Operand* ops){ · 7 unmodified lines
314306
315307 /* This is special: First operand is optional */
316308 static void asm_jal_opcode(TCCState *s1, int token){
317− static const Operand ra = {.type = OP_REG, .reg = 1};
318− static const Operand zero = {.type = OP_REG};
319309 Operand ops[2];
320310
321311 if (token == TOK_ASM_j ){
@@ -333,8 +323,6 @@ static void asm_jal_opcode(TCCState *s1, int token){ · 11 unmodified lines
333323
334324 /* This is special: It can be a pseudointruction or a instruction */
335325 static void asm_jalr_opcode(TCCState *s1, int token){
336− static const Operand zimm = {.type = OP_IM12S};
337− static const Operand ra = {.type = OP_REG, .reg = 1};
338326 Operand ops[3];
339327 Operand op;
340328
@@ -355,7 +343,7 @@ static void asm_jalr_opcode(TCCState *s1, int token){ · 14 unmodified lines
355343 /* `X, (Y)` case*/
356344 next();
357345 parse_operand(s1, &ops[1]);
358− if ( tok == ')') next(); else expect("')'");
346+ skip(')');
359347 ops[2] = zimm;
360348 } else {
361349 parse_operand(s1, &ops[2]);
@@ -363,7 +351,7 @@ static void asm_jalr_opcode(TCCState *s1, int token){ · 1 unmodified line
363351 /* `X, imm(Y)` case*/
364352 next();
365353 parse_operand(s1, &ops[1]);
366− if ( tok == ')') next(); else expect("')'");
354+ skip(')');
367355 } else {
368356 /* `X, Y` case*/
369357 /* we parsed Y thinking it was imm, swap and default imm to zero */
@@ -382,8 +370,6 @@ static void asm_unary_opcode(TCCState *s1, int token) · 12 unmodified lines
382370 {
383371 uint32_t opcode = (0x1C << 2) | 3 | (2 << 12);
384372 Operand op;
385− static const Operand zero = {.type = OP_REG};
386− static const Operand zimm = {.type = OP_IM12S};
387373
388374 parse_operands(s1, &op, 1);
389375 /* Note: Those all map to CSR--so they are pseudo-instructions. */
@@ -451,14 +437,11 @@ static void asm_emit_u(int token, uint32_t opcode, const Operand* rd, const Oper · 61 unmodified lines
451437 {
452438 if (rd->type != OP_REG) {
453439 tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
454− return;
455440 }
456441 if (rs2->type != OP_IM12S && rs2->type != OP_IM32) {
457442 tcc_error("'%s': Expected second source operand that is an immediate value", get_tok_str(token, NULL));
458− return;
459443 } else if (rs2->e.v >= 0x100000) {
460444 tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 0xfffff", get_tok_str(token, NULL));
461− return;
462445 }
463446 /* U-type instruction:
464447 31...12 imm[31:12]
@@ -486,7 +469,7 @@ static void asm_fence_opcode(TCCState *s1, int token){ · 21 unmodified lines
486469 if ( pred > 0xF || pred < 0) {
487470 tcc_error("'%s': Expected first operand that is a valid predecessor operand", get_tok_str(token, NULL));
488471 }
489− if ( tok == ',') next(); else expect("','");
472+ skip(',');
490473 succ = parse_fence_operand();
491474 if ( succ > 0xF || succ < 0) {
492475 tcc_error("'%s': Expected second operand that is a valid successor operand", get_tok_str(token, NULL));
@@ -497,8 +480,7 @@ static void asm_fence_opcode(TCCState *s1, int token){ · 4 unmodified lines
497480
498481 static void asm_binary_opcode(TCCState* s1, int token)
499482 {
500− static const Operand zero = {.type = OP_REG, .reg = 0};
501− Operand imm = {.type = OP_IM12S, .e = {.v = 0}};
483+ Operand imm = { OP_IM12S };
502484 Operand ops[2];
503485 int32_t lo;
504486 uint32_t hi;
@@ -710,15 +692,12 @@ static void asm_emit_r(int token, uint32_t opcode, const Operand* rd, const Oper · 205 unmodified lines
710692 {
711693 if (rd->type != OP_REG) {
712694 tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
713− return;
714695 }
715696 if (rs1->type != OP_REG) {
716697 tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
717− return;
718698 }
719699 if (rs2->type != OP_REG) {
720700 tcc_error("'%s': Expected second source operand that is a register or immediate", get_tok_str(token, NULL));
721− return;
722701 }
723702 /* R-type instruction:
724703 31...25 funct7
@@ -735,15 +714,12 @@ static void asm_emit_i(int token, uint32_t opcode, const Operand* rd, const Oper · 10 unmodified lines
735714 {
736715 if (rd->type != OP_REG) {
737716 tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
738− return;
739717 }
740718 if (rs1->type != OP_REG) {
741719 tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
742− return;
743720 }
744721 if (rs2->type != OP_IM12S) {
745722 tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 8191", get_tok_str(token, NULL));
746− return;
747723 }
748724 /* I-type instruction:
749725 31...20 imm[11:0]
@@ -761,11 +737,9 @@ static void asm_emit_j(int token, uint32_t opcode, const Operand* rd, const Oper · 11 unmodified lines
761737
762738 if (rd->type != OP_REG) {
763739 tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
764− return;
765740 }
766741 if (rs2->type != OP_IM12S && rs2->type != OP_IM32) {
767742 tcc_error("'%s': Expected second source operand that is an immediate value", get_tok_str(token, NULL));
768− return;
769743 }
770744
771745 imm = rs2->e.v;
@@ -773,12 +747,10 @@ static void asm_emit_j(int token, uint32_t opcode, const Operand* rd, const Oper · 1 unmodified line
773747 /* even offsets in a +- 1 MiB range */
774748 if ((int)imm > (1 << 20) -1 || (int)imm <= -1 * ((1 << 20) -1)) {
775749 tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 0x1fffff", get_tok_str(token, NULL));
776− return;
777750 }
778751
779752 if (imm & 1) {
780753 tcc_error("'%s': Expected second source operand that is an even immediate value", get_tok_str(token, NULL));
781− return;
782754 }
783755 /* J-type instruction:
784756 31 imm[20]
@@ -851,11 +823,11 @@ static void asm_mem_access_opcode(TCCState *s1, int token) · 66 unmodified lines
851823 }
852824 }
853825
854−static void asm_branch_opcode(TCCState *s1, int token, int argc){
826+static void asm_branch_opcode(TCCState *s1, int token, int argc)
827+{
855828 Operand ops[3];
856− Operand zero = {.type = OP_REG};
857829 parse_operands(s1, &ops[0], argc-1);
858− if ( tok == ',') next(); else { expect(","); }
830+ skip(',');
859831 parse_branch_offset_operand(s1, &ops[argc-1]);
860832
861833 switch(token){
@@ -1118,22 +1090,21 @@ static void asm_ternary_opcode(TCCState *s1, int token) · 256 unmodified lines
11181090
11191091 static void asm_atomic_opcode(TCCState *s1, int token)
11201092 {
1121− static const Operand zero = {.type = OP_REG};
11221093 Operand ops[3];
11231094
11241095 parse_operand(s1, &ops[0]);
1125− if ( tok == ',') next(); else expect("','");
1096+ skip(',');
11261097
11271098 if ( token <= TOK_ASM_lr_d_aqrl && token >= TOK_ASM_lr_w ) {
11281099 ops[1] = zero;
11291100 } else {
11301101 parse_operand(s1, &ops[1]);
1131− if ( tok == ',') next(); else expect("','");
1102+ skip(',');
11321103 }
11331104
1134− if ( tok == '(') next(); else expect("'('");
1105+ skip('(');
11351106 parse_operand(s1, &ops[2]);
1136− if ( tok == ')') next(); else expect("')'");
1107+ skip(')');
11371108
11381109 switch(token){
11391110 case TOK_ASM_lr_w:
@@ -1217,15 +1188,12 @@ static void asm_emit_s(int token, uint32_t opcode, const Operand* rs1, const Ope · 77 unmodified lines
12171188 {
12181189 if (rs1->type != OP_REG) {
12191190 tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
1220− return;
12211191 }
12221192 if (rs2->type != OP_REG) {
12231193 tcc_error("'%s': Expected second source operand that is a register", get_tok_str(token, NULL));
1224− return;
12251194 }
12261195 if (imm->type != OP_IM12S) {
12271196 tcc_error("'%s': Expected third operand that is an immediate value between 0 and 8191", get_tok_str(token, NULL));
1228− return;
12291197 }
12301198 {
12311199 uint16_t v = imm->e.v;
@@ -1247,15 +1215,12 @@ static void asm_emit_b(int token, uint32_t opcode, const Operand *rs1, const Ope · 15 unmodified lines
12471215
12481216 if (rs1->type != OP_REG) {
12491217 tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
1250− return;
12511218 }
12521219 if (rs2->type != OP_REG) {
12531220 tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
1254− return;
12551221 }
12561222 if (imm->type != OP_IM12S) {
12571223 tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 8191", get_tok_str(token, NULL));
1258− return;
12591224 }
12601225
12611226 offset = imm->e.v;
@@ -1541,7 +1506,6 @@ static int asm_parse_csrvar(int t) · 279 unmodified lines
15411506 ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
15421507 {
15431508 int r, reg, val;
1544− char buf[64];
15451509
15461510 r = sv->r;
15471511 if ((r & VT_VALMASK) == VT_CONST) {
@@ -1572,13 +1536,11 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier) · 24 unmodified lines
15721536 if (modifier == 'z' && sv->c.i == 0) {
15731537 cstr_cat(add_str, "zero", -1);
15741538 } else {
1575− snprintf(buf, sizeof(buf), "%d", (int) sv->c.i);
1576− cstr_cat(add_str, buf, -1);
1539+ cstr_printf(add_str, "%d", (int) sv->c.i);
15771540 }
15781541 no_offset:;
15791542 } else if ((r & VT_VALMASK) == VT_LOCAL) {
1580− snprintf(buf, sizeof(buf), "%d", (int) sv->c.i);
1581− cstr_cat(add_str, buf, -1);
1543+ cstr_printf(add_str, "%d", (int) sv->c.i);
15821544 } else if (r & VT_LVAL) {
15831545 reg = r & VT_VALMASK;
15841546 if (reg >= VT_CONST)
@@ -1591,8 +1553,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier) · 6 unmodified lines
15911553 /* general purpose register */
15921554 reg = TOK_ASM_x0 + reg;
15931555 }
1594− snprintf(buf, sizeof(buf), "%s", get_tok_str(reg, NULL));
1595− cstr_cat(add_str, buf, -1);
1556+ cstr_cat(add_str, get_tok_str(reg, NULL), -1);
15961557 } else {
15971558 /* register case */
15981559 reg = r & VT_VALMASK;
@@ -1606,8 +1567,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier) · 7 unmodified lines
16061567 /* general purpose register */
16071568 reg = TOK_ASM_x0 + reg;
16081569 }
1609− snprintf(buf, sizeof(buf), "%s", get_tok_str(reg, NULL));
1610− cstr_cat(add_str, buf, -1);
1570+ cstr_cat(add_str, get_tok_str(reg, NULL), -1);
16111571 }
16121572 }
16131573
@@ -1775,12 +1735,9 @@ static inline int constraint_priority(const char *str) · 161 unmodified lines
17751735 pr = 4;
17761736 break;
17771737 case 'v':
1778− tcc_error("unimp: vector constraints '%d'", c);
1779− pr = 0;
1780− break;
1738+ tcc_error("unimp: constraint '%c'", c);
17811739 default:
17821740 tcc_error("unknown constraint '%d'", c);
1783− pr = 0;
17841741 }
17851742 if (pr > priority)
17861743 priority = pr;
@@ -2093,12 +2050,10 @@ static void asm_emit_ca(int token, uint16_t opcode, const Operand *rd, const Ope · 306 unmodified lines
20932050
20942051 if (rd->type != OP_REG) {
20952052 tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
2096− return;
20972053 }
20982054
20992055 if (rs2->type != OP_REG) {
21002056 tcc_error("'%s': Expected source operand that is a register", get_tok_str(token, NULL));
2101− return;
21022057 }
21032058
21042059 /* subtract index of x8 */
@@ -2108,12 +2063,10 @@ static void asm_emit_ca(int token, uint16_t opcode, const Operand *rd, const Ope · 3 unmodified lines
21082063 /* only registers {x,f}8 to {x,f}15 are valid (3-bit) */
21092064 if (dst > 7) {
21102065 tcc_error("'%s': Expected destination operand that is a valid C-extension register", get_tok_str(token, NULL));
2111− return;
21122066 }
21132067
21142068 if (src > 7) {
21152069 tcc_error("'%s': Expected source operand that is a valid C-extension register", get_tok_str(token, NULL));
2116− return;
21172070 }
21182071
21192072 /* CA-type instruction:
@@ -2133,26 +2086,22 @@ static void asm_emit_cb(int token, uint16_t opcode, const Operand *rs1, const Op · 13 unmodified lines
21332086
21342087 if (rs1->type != OP_REG) {
21352088 tcc_error("'%s': Expected source operand that is a register", get_tok_str(token, NULL));
2136− return;
21372089 }
21382090
21392091 if (imm->type != OP_IM12S && imm->type != OP_IM32) {
21402092 tcc_error("'%s': Expected source operand that is an immediate value", get_tok_str(token, NULL));
2141− return;
21422093 }
21432094
21442095 offset = imm->e.v;
21452096
21462097 if (offset & 1) {
21472098 tcc_error("'%s': Expected source operand that is an even immediate value", get_tok_str(token, NULL));
2148− return;
21492099 }
21502100
21512101 src = rs1->reg - 8;
21522102
21532103 if (src > 7) {
21542104 tcc_error("'%s': Expected source operand that is a valid C-extension register", get_tok_str(token, NULL));
2155− return;
21562105 }
21572106
21582107 /* CB-type instruction:
@@ -2187,12 +2136,10 @@ static void asm_emit_ci(int token, uint16_t opcode, const Operand *rd, const Ope · 28 unmodified lines
21872136
21882137 if (rd->type != OP_REG) {
21892138 tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
2190− return;
21912139 }
21922140
21932141 if (imm->type != OP_IM12S && imm->type != OP_IM32) {
21942142 tcc_error("'%s': Expected source operand that is an immediate value", get_tok_str(token, NULL));
2195− return;
21962143 }
21972144
21982145 immediate = imm->e.v;
@@ -2241,31 +2188,26 @@ static void asm_emit_ciw(int token, uint16_t opcode, const Operand *rd, const Op · 42 unmodified lines
22412188
22422189 if (rd->type != OP_REG) {
22432190 tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
2244− return;
22452191 }
22462192
22472193 if (imm->type != OP_IM12S && imm->type != OP_IM32) {
22482194 tcc_error("'%s': Expected source operand that is an immediate value", get_tok_str(token, NULL));
2249− return;
22502195 }
22512196
22522197 dst = rd->reg - 8;
22532198
22542199 if (dst > 7) {
22552200 tcc_error("'%s': Expected destination operand that is a valid C-extension register", get_tok_str(token, NULL));
2256− return;
22572201 }
22582202
22592203 nzuimm = imm->e.v;
22602204
22612205 if (nzuimm > 0x3fc) {
22622206 tcc_error("'%s': Expected source operand that is an immediate value between 0 and 0x3ff", get_tok_str(token, NULL));
2263− return;
22642207 }
22652208
22662209 if (nzuimm & 3) {
22672210 tcc_error("'%s': Expected source operand that is a non-zero immediate value divisible by 4", get_tok_str(token, NULL));
2268− return;
22692211 }
22702212
22712213 /* CIW-type instruction:
@@ -2285,14 +2227,12 @@ static void asm_emit_cj(int token, uint16_t opcode, const Operand *imm) · 13 unmodified lines
22852227 /* +-2 KiB range */
22862228 if (imm->type != OP_IM12S) {
22872229 tcc_error("'%s': Expected source operand that is a 12-bit immediate value", get_tok_str(token, NULL));
2288− return;
22892230 }
22902231
22912232 offset = imm->e.v;
22922233
22932234 if (offset & 1) {
22942235 tcc_error("'%s': Expected source operand that is an even immediate value", get_tok_str(token, NULL));
2295− return;
22962236 }
22972237
22982238 /* CJ-type instruction:
@@ -2311,17 +2251,14 @@ static void asm_emit_cl(int token, uint16_t opcode, const Operand *rd, const Ope · 12 unmodified lines
23112251
23122252 if (rd->type != OP_REG) {
23132253 tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
2314− return;
23152254 }
23162255
23172256 if (rs1->type != OP_REG) {
23182257 tcc_error("'%s': Expected source operand that is a register", get_tok_str(token, NULL));
2319− return;
23202258 }
23212259
23222260 if (imm->type != OP_IM12S && imm->type != OP_IM32) {
23232261 tcc_error("'%s': Expected source operand that is an immediate value", get_tok_str(token, NULL));
2324− return;
23252262 }
23262263
23272264 dst = rd->reg - 8;
@@ -2329,24 +2266,20 @@ static void asm_emit_cl(int token, uint16_t opcode, const Operand *rd, const Ope · 1 unmodified line
23292266
23302267 if (dst > 7) {
23312268 tcc_error("'%s': Expected destination operand that is a valid C-extension register", get_tok_str(token, NULL));
2332− return;
23332269 }
23342270
23352271 if (src > 7) {
23362272 tcc_error("'%s': Expected source operand that is a valid C-extension register", get_tok_str(token, NULL));
2337− return;
23382273 }
23392274
23402275 offset = imm->e.v;
23412276
23422277 if (offset > 0xff) {
23432278 tcc_error("'%s': Expected source operand that is an immediate value between 0 and 0xff", get_tok_str(token, NULL));
2344− return;
23452279 }
23462280
23472281 if (offset & 3) {
23482282 tcc_error("'%s': Expected source operand that is an immediate value divisible by 4", get_tok_str(token, NULL));
2349− return;
23502283 }
23512284
23522285 /* CL-type instruction:
@@ -2378,12 +2311,10 @@ static void asm_emit_cr(int token, uint16_t opcode, const Operand *rd, const Ope · 25 unmodified lines
23782311 {
23792312 if (rd->type != OP_REG) {
23802313 tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
2381− return;
23822314 }
23832315
23842316 if (rs2->type != OP_REG) {
23852317 tcc_error("'%s': Expected source operand that is a register", get_tok_str(token, NULL));
2386− return;
23872318 }
23882319
23892320 /* CR-type instruction:
@@ -2403,17 +2334,14 @@ static void asm_emit_cs(int token, uint16_t opcode, const Operand *rs2, const Op · 13 unmodified lines
24032334
24042335 if (rs2->type != OP_REG) {
24052336 tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
2406− return;
24072337 }
24082338
24092339 if (rs1->type != OP_REG) {
24102340 tcc_error("'%s': Expected source operand that is a register", get_tok_str(token, NULL));
2411− return;
24122341 }
24132342
24142343 if (imm->type != OP_IM12S && imm->type != OP_IM32) {
24152344 tcc_error("'%s': Expected source operand that is an immediate value", get_tok_str(token, NULL));
2416− return;
24172345 }
24182346
24192347 base = rs1->reg - 8;
@@ -2421,24 +2349,20 @@ static void asm_emit_cs(int token, uint16_t opcode, const Operand *rs2, const Op · 1 unmodified line
24212349
24222350 if (base > 7) {
24232351 tcc_error("'%s': Expected destination operand that is a valid C-extension register", get_tok_str(token, NULL));
2424− return;
24252352 }
24262353
24272354 if (src > 7) {
24282355 tcc_error("'%s': Expected source operand that is a valid C-extension register", get_tok_str(token, NULL));
2429− return;
24302356 }
24312357
24322358 offset = imm->e.v;
24332359
24342360 if (offset > 0xff) {
24352361 tcc_error("'%s': Expected source operand that is an immediate value between 0 and 0xff", get_tok_str(token, NULL));
2436− return;
24372362 }
24382363
24392364 if (offset & 3) {
24402365 tcc_error("'%s': Expected source operand that is an immediate value divisible by 4", get_tok_str(token, NULL));
2441− return;
24422366 }
24432367
24442368 /* CS-type instruction:
@@ -2471,24 +2395,20 @@ static void asm_emit_css(int token, uint16_t opcode, const Operand *rs2, const O · 26 unmodified lines
24712395
24722396 if (rs2->type != OP_REG) {
24732397 tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
2474− return;
24752398 }
24762399
24772400 if (imm->type != OP_IM12S && imm->type != OP_IM32) {
24782401 tcc_error("'%s': Expected source operand that is an immediate value", get_tok_str(token, NULL));
2479− return;
24802402 }
24812403
24822404 offset = imm->e.v;
24832405
24842406 if (offset > 0xff) {
24852407 tcc_error("'%s': Expected source operand that is an immediate value between 0 and 0xff", get_tok_str(token, NULL));
2486− return;
24872408 }
24882409
24892410 if (offset & 3) {
24902411 tcc_error("'%s': Expected source operand that is an immediate value divisible by 4", get_tok_str(token, NULL));
2491− return;
24922412 }
24932413
24942414 /* CSS-type instruction:
riscv64-link.c+3−3
@@ -24,7 +24,7 @@ · 23 unmodified lines
2424
2525 /* Returns 1 for a code relocation, 0 for a data relocation. For unknown
2626 relocations, returns -1. */
27−int code_reloc (int reloc_type)
27+ST_FUNC int code_reloc (int reloc_type)
2828 {
2929 switch (reloc_type) {
3030
@@ -62,7 +62,7 @@ int code_reloc (int reloc_type) · 31 unmodified lines
6262 /* Returns an enumerator to describe whether and when the relocation needs a
6363 GOT and/or PLT entry to be created. See tcc.h for a description of the
6464 different values. */
65−int gotplt_entry_type (int reloc_type)
65+ST_FUNC int gotplt_entry_type (int reloc_type)
6666 {
6767 switch (reloc_type) {
6868 case R_RISCV_ALIGN:
@@ -169,7 +169,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 100 unmodified lines
169169 }
170170 }
171171
172−void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
172+ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
173173 addr_t addr, addr_t val)
174174 {
175175 uint64_t off64;
tcc.h+4−5
@@ -89,7 +89,6 @@ extern long double strtold (const char *__nptr, char **__endptr); · 88 unmodified lines
8989 # ifndef va_copy
9090 # define va_copy(a,b) a = b
9191 # endif
92−# undef CONFIG_TCC_STATIC
9392 #endif
9493
9594 #ifndef O_BINARY
@@ -487,7 +486,7 @@ typedef int nwchar_t; · 391 unmodified lines
487486 typedef struct CString {
488487 int size; /* size in bytes */
489488 int size_allocated;
490− void *data; /* either 'char *' or 'nwchar_t *' */
489+ char *data; /* nwchar_t* in cases */
491490 } CString;
492491
493492 /* type definition */
@@ -1157,7 +1156,7 @@ struct filespec { · 663 unmodified lines
11571156 #define TOK_TWODOTS 0xa2 /* C++ token ? */
11581157 #define TOK_TWOSHARPS 0xa3 /* ## preprocessing token */
11591158 #define TOK_PLCHLDR 0xa4 /* placeholder token as defined in C99 */
1160−#define TOK_PPJOIN 0xa6 /* A '##' in the right position to mean pasting */
1159+#define TOK_PPJOIN (TOK_TWOSHARPS | SYM_FIELD) /* A '##' in a macro to mean pasting */
11611160 #define TOK_SOTYPE 0xa7 /* alias of '(' for parsing sizeof (type) */
11621161
11631162 /* assignment operators */
@@ -1253,8 +1252,8 @@ ST_FUNC void libc_free(void *ptr); · 89 unmodified lines
12531252 PUB_FUNC int _tcc_error_noabort(const char *fmt, ...) PRINTF_LIKE(1,2);
12541253 PUB_FUNC NORETURN void _tcc_error(const char *fmt, ...) PRINTF_LIKE(1,2);
12551254 PUB_FUNC void _tcc_warning(const char *fmt, ...) PRINTF_LIKE(1,2);
1256−#define tcc_internal_error(msg) tcc_error("internal compiler error\n"\
1257− "%s:%d: in %s(): " msg, __FILE__,__LINE__,__FUNCTION__)
1255+#define tcc_internal_error(msg) \
1256+ tcc_error("internal compiler error in %s:%d: %s", __FUNCTION__,__LINE__,msg)
12581257
12591258 /* other utilities */
12601259 ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data);
tccelf.c+9−20
@@ -153,9 +153,12 @@ ST_FUNC void tccelf_begin_file(TCCState *s1) · 152 unmodified lines
153153 s = s1->symtab, s->reloc = s->hash, s->hash = NULL;
154154 #if defined TCC_TARGET_X86_64 && defined TCC_TARGET_PE
155155 s1->uw_sym = 0;
156+ s1->uw_offs = 0;
156157 #endif
157158 }
158159
160+static void update_relocs(TCCState *s1, Section *s, int *old_to_new_syms, int first_sym);
161+
159162 /* At the end of compilation, convert any UNDEF syms to global, and merge
160163 with previously existing symbols */
161164 ST_FUNC void tccelf_end_file(TCCState *s1)
@@ -172,7 +175,6 @@ ST_FUNC void tccelf_end_file(TCCState *s1) · 10 unmodified lines
172175
173176 for (i = 0; i < nb_syms; ++i) {
174177 ElfSym *sym = (ElfSym*)s->data + first_sym + i;
175−
176178 if (sym->st_shndx == SHN_UNDEF) {
177179 int sym_bind = ELFW(ST_BIND)(sym->st_info);
178180 int sym_type = ELFW(ST_TYPE)(sym->st_info);
@@ -187,26 +189,12 @@ ST_FUNC void tccelf_end_file(TCCState *s1) · 8 unmodified lines
187189 #endif
188190 sym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
189191 }
190−
191192 tr[i] = set_elf_sym(s, sym->st_value, sym->st_size, sym->st_info,
192193 sym->st_other, sym->st_shndx, (char*)s->link->data + sym->st_name);
193194 }
194195 /* now update relocations */
195− for (i = 1; i < s1->nb_sections; i++) {
196− Section *sr = s1->sections[i];
197− if (sr->sh_type == SHT_RELX && sr->link == s) {
198− ElfW_Rel *rel = (ElfW_Rel*)(sr->data + sr->sh_offset);
199− ElfW_Rel *rel_end = (ElfW_Rel*)(sr->data + sr->data_offset);
200− for (; rel < rel_end; ++rel) {
201− int n = ELFW(R_SYM)(rel->r_info) - first_sym;
202− if (n < 0) /* zero sym_index in reloc (can happen with asm) */
203− continue;
204− rel->r_info = ELFW(R_INFO)(tr[n], ELFW(R_TYPE)(rel->r_info));
205− }
206− }
207− }
196+ update_relocs(s1, s, tr, first_sym);
208197 tcc_free(tr);
209−
210198 /* record text/data/bss output for -bench info */
211199 for (i = 0; i < 4; ++i) {
212200 s = s1->sections[i + 1];
@@ -801,7 +789,7 @@ ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc) · 588 unmodified lines
801789 return &s1->sym_attrs[index];
802790 }
803791
804−static void modify_reloctions_old_to_new(TCCState *s1, Section *s, int *old_to_new_syms)
792+static void update_relocs(TCCState *s1, Section *s, int *old_to_new_syms, int first_sym)
805793 {
806794 int i, type, sym_index;
807795 Section *sr;
@@ -813,6 +801,8 @@ static void modify_reloctions_old_to_new(TCCState *s1, Section *s, int *old_to_n · 5 unmodified lines
813801 for_each_elem(sr, 0, rel, ElfW_Rel) {
814802 sym_index = ELFW(R_SYM)(rel->r_info);
815803 type = ELFW(R_TYPE)(rel->r_info);
804+ if ((sym_index -= first_sym) < 0)
805+ continue; /* zero sym_index in reloc (can happen with asm) */
816806 sym_index = old_to_new_syms[sym_index];
817807 rel->r_info = ELFW(R_INFO)(sym_index, type);
818808 }
@@ -863,8 +853,7 @@ static void sort_syms(TCCState *s1, Section *s) · 44 unmodified lines
863853 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
864854 tcc_free(new_syms);
865855
866− modify_reloctions_old_to_new(s1, s, old_to_new_syms);
867−
856+ update_relocs(s1, s, old_to_new_syms, 0);
868857 tcc_free(old_to_new_syms);
869858 }
870859
@@ -1012,7 +1001,7 @@ static void update_gnu_hash(TCCState *s1, Section *gnu_hash) · 141 unmodified lines
10121001 tcc_free(buck);
10131002 tcc_free(nextbuck);
10141003
1015− modify_reloctions_old_to_new(s1, dynsym, old_to_new_syms);
1004+ update_relocs(s1, dynsym, old_to_new_syms, 0);
10161005
10171006 /* modify the versions */
10181007 vs = versym_section;
tccgen.c+51−54
@@ -657,8 +657,6 @@ ST_FUNC Sym *sym_find2(Sym *s, int v) · 656 unmodified lines
657657 while (s) {
658658 if (s->v == v)
659659 return s;
660− else if (s->v == -1)
661− return NULL;
662660 s = s->prev;
663661 }
664662 return NULL;
@@ -1398,6 +1396,7 @@ ST_FUNC void save_reg_upstack(int r, int n) · 733 unmodified lines
13981396 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
13991397 } else {
14001398 p->r = VT_LVAL | VT_LOCAL;
1399+ p->type.t &= ~VT_ARRAY; /* cannot combine VT_LVAL with VT_ARRAY */
14011400 }
14021401 p->sym = NULL;
14031402 p->r2 = VT_CONST;
@@ -2838,14 +2837,25 @@ static int compare_types(CType *type1, CType *type2, int unqualified) · 1434 unmodified lines
28382837 }
28392838 }
28402839
2840+#define CMP_OP 'C'
2841+#define SHIFT_OP 'S'
2842+
28412843 /* Check if OP1 and OP2 can be "combined" with operation OP, the combined
28422844 type is stored in DEST if non-null (except for pointer plus/minus) . */
28432845 static int combine_types(CType *dest, SValue *op1, SValue *op2, int op)
28442846 {
2845− CType *type1 = &op1->type, *type2 = &op2->type, type;
2846− int t1 = type1->t, t2 = type2->t, bt1 = t1 & VT_BTYPE, bt2 = t2 & VT_BTYPE;
2847+ CType *type1, *type2, type;
2848+ int t1, t2, bt1, bt2;
28472849 int ret = 1;
28482850
2851+ /* for shifts, 'combine' only left operand */
2852+ if (op == SHIFT_OP)
2853+ op2 = op1;
2854+
2855+ type1 = &op1->type, type2 = &op2->type;
2856+ t1 = type1->t, t2 = type2->t;
2857+ bt1 = t1 & VT_BTYPE, bt2 = t2 & VT_BTYPE;
2858+
28492859 type.t = VT_VOID;
28502860 type.ref = NULL;
28512861
@@ -2854,7 +2864,10 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) · 2 unmodified lines
28542864 /* NOTE: as an extension, we accept void on only one side */
28552865 type.t = VT_VOID;
28562866 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
2857− if (op == '+') ; /* Handled in caller */
2867+ if (op == '+') {
2868+ if (!is_integer_btype(bt1 == VT_PTR ? bt2 : bt1))
2869+ ret = 0;
2870+ }
28582871 /* http://port70.net/~nsz/c/c99/n1256.html#6.5.15p6 */
28592872 /* If one is a null ptr constant the result type is the other. */
28602873 else if (is_null_pointer (op2)) type = *type1;
@@ -2862,7 +2875,7 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) · 1 unmodified line
28622875 else if (bt1 != bt2) {
28632876 /* accept comparison or cond-expr between pointer and integer
28642877 with a warning */
2865− if ((op == '?' || TOK_ISCOND(op))
2878+ if ((op == '?' || op == CMP_OP)
28662879 && (is_integer_btype(bt1) || is_integer_btype(bt2)))
28672880 tcc_warning("pointer/integer mismatch in %s",
28682881 op == '?' ? "conditional expression" : "comparison");
@@ -2877,7 +2890,7 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) · 8 unmodified lines
28772890 int newquals, copied = 0;
28782891 if (pbt1 != VT_VOID && pbt2 != VT_VOID
28792892 && !compare_types(pt1, pt2, 1/*unqualif*/)) {
2880− if (op != '?' && !TOK_ISCOND(op))
2893+ if (op != '?' && op != CMP_OP)
28812894 ret = 0;
28822895 else
28832896 type_incompatibility_warning(type1, type2,
@@ -2918,7 +2931,7 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) · 34 unmodified lines
29182931 }
29192932 }
29202933 }
2921− if (TOK_ISCOND(op))
2934+ if (op == CMP_OP)
29222935 type.t = VT_SIZE_T;
29232936 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
29242937 if (op != '?' || !compare_types(type1, type2, 1))
@@ -2961,6 +2974,12 @@ ST_FUNC void gen_op(int op) · 36 unmodified lines
29612974 {
29622975 int t1, t2, bt1, bt2, t;
29632976 CType type1, combtype;
2977+ int op_class = op;
2978+
2979+ if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
2980+ op_class = SHIFT_OP;
2981+ else if (TOK_ISCOND(op)) /* == != > ... */
2982+ op_class = CMP_OP;
29642983
29652984 redo:
29662985 t1 = vtop[-1].type.t;
@@ -2980,18 +2999,19 @@ redo: · 13 unmodified lines
29802999 vswap();
29813000 }
29823001 goto redo;
2983− } else if (!combine_types(&combtype, vtop - 1, vtop, op)) {
3002+ } else if (!combine_types(&combtype, vtop - 1, vtop, op_class)) {
3003+op_err:
29843004 tcc_error("invalid operand types for binary operation");
29853005 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
29863006 /* at least one operand is a pointer */
29873007 /* relational op: must be both pointers */
29883008 int align;
2989− if (TOK_ISCOND(op))
3009+ if (op_class == CMP_OP)
29903010 goto std_op;
29913011 /* if both pointers, then it must be the '-' op */
29923012 if (bt1 == VT_PTR && bt2 == VT_PTR) {
29933013 if (op != '-')
2994− tcc_error("cannot use pointers here");
3014+ goto op_err;
29953015 vpush_type_size(pointed_type(&vtop[-1].type), &align);
29963016 vtop->type.t &= ~VT_UNSIGNED;
29973017 vrott(3);
@@ -3002,14 +3022,15 @@ redo: · 4 unmodified lines
30023022 } else {
30033023 /* exactly one pointer : must be '+' or '-'. */
30043024 if (op != '-' && op != '+')
3005− tcc_error("cannot use pointers here");
3025+ goto op_err;
30063026 /* Put pointer as first operand */
30073027 if (bt2 == VT_PTR) {
30083028 vswap();
30093029 t = t1, t1 = t2, t2 = t;
3030+ bt2 = bt1;
30103031 }
30113032 #if PTR_SIZE == 4
3012− if ((vtop[0].type.t & VT_BTYPE) == VT_LLONG)
3033+ if (bt2 == VT_LLONG)
30133034 /* XXX: truncate here because gen_opl can't handle ptr + long long */
30143035 gen_cast_s(VT_INT);
30153036 #endif
@@ -3039,17 +3060,15 @@ redo: · 23 unmodified lines
30393060 /* floats can only be used for a few operations */
30403061 if (is_float(combtype.t)
30413062 && op != '+' && op != '-' && op != '*' && op != '/'
3042− && !TOK_ISCOND(op))
3043− tcc_error("invalid operands for binary operation");
3044− else if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL) {
3045− t = bt1 == VT_LLONG ? VT_LLONG : VT_INT;
3046− if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (t | VT_UNSIGNED))
3047− t |= VT_UNSIGNED;
3048− t |= (VT_LONG & t1);
3049− combtype.t = t;
3063+ && op_class != CMP_OP) {
3064+ goto op_err;
30503065 }
30513066 std_op:
30523067 t = t2 = combtype.t;
3068+ /* special case for shifts and long long: we keep the shift as
3069+ an integer */
3070+ if (op_class == SHIFT_OP)
3071+ t2 = VT_INT;
30533072 /* XXX: currently, some unsigned operations are explicit, so
30543073 we modify them here */
30553074 if (t & VT_UNSIGNED) {
@@ -3071,16 +3090,12 @@ redo: · 15 unmodified lines
30713090 vswap();
30723091 gen_cast_s(t);
30733092 vswap();
3074− /* special case for shifts and long long: we keep the shift as
3075− an integer */
3076− if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
3077− t2 = VT_INT;
30783093 gen_cast_s(t2);
30793094 if (is_float(t))
30803095 gen_opif(op);
30813096 else
30823097 gen_opic(op);
3083− if (TOK_ISCOND(op)) {
3098+ if (op_class == CMP_OP) {
30843099 /* relational op: the result is an int */
30853100 vtop->type.t = VT_INT;
30863101 } else {
@@ -3416,13 +3431,10 @@ ST_FUNC int type_size(CType *type, int *a) · 329 unmodified lines
34163431 } else if (bt == VT_PTR) {
34173432 if (type->t & VT_ARRAY) {
34183433 int ts;
3419−
34203434 s = type->ref;
34213435 ts = type_size(&s->type, a);
3422−
34233436 if (ts < 0 && s->c < 0)
34243437 ts = -ts;
3425−
34263438 return ts * s->c;
34273439 } else {
34283440 *a = PTR_SIZE;
@@ -3435,18 +3447,9 @@ ST_FUNC int type_size(CType *type, int *a) · 6 unmodified lines
34353447 *a = LDOUBLE_ALIGN;
34363448 return LDOUBLE_SIZE;
34373449 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
3438−#ifdef TCC_TARGET_I386
3439−#ifdef TCC_TARGET_PE
3440− *a = 8;
3441−#else
3442− *a = 4;
3443−#endif
3444−#elif defined(TCC_TARGET_ARM)
3445−#ifdef TCC_ARM_EABI
3446− *a = 8;
3447−#else
3450+#if (defined TCC_TARGET_I386 && !defined TCC_TARGET_PE) \
3451+ || (defined TCC_TARGET_ARM && !defined TCC_ARM_EABI)
34483452 *a = 4;
3449−#endif
34503453 #else
34513454 *a = 8;
34523455 #endif
@@ -3974,12 +3977,12 @@ redo: · 521 unmodified lines
39743977 case TOK_FASTCALL2:
39753978 case TOK_FASTCALL3:
39763979 ad->f.func_call = FUNC_FASTCALLW;
3977− break;
3980+ break;
39783981 case TOK_THISCALL1:
39793982 case TOK_THISCALL2:
39803983 case TOK_THISCALL3:
39813984 ad->f.func_call = FUNC_THISCALL;
3982− break;
3985+ break;
39833986 #endif
39843987 case TOK_MODE:
39853988 skip('(');
@@ -5714,16 +5717,12 @@ ST_FUNC void unary(void) · 1728 unmodified lines
57145717 case TOK_builtin_return_address:
57155718 {
57165719 int tok1 = tok;
5717− int64_t level;
5720+ int level;
57185721 next();
57195722 skip('(');
5720− level = expr_const64();
5721− if (level < 0) {
5722− tcc_error("%s only takes positive integers",
5723− tok1 == TOK_builtin_return_address ?
5724− "__builtin_return_address" :
5725− "__builtin_frame_address");
5726− }
5723+ level = expr_const();
5724+ if (level < 0)
5725+ tcc_error("%s only takes positive integers", get_tok_str(tok1, 0));
57275726 skip(')');
57285727 type.t = VT_VOID;
57295728 mk_pointer(&type);
@@ -7400,12 +7399,10 @@ static void init_putz(init_params *p, unsigned long c, int size) · 1670 unmodified lines
74007399 } else {
74017400 vpush_helper_func(TOK_memset);
74027401 vseti(VT_LOCAL, c);
7403−#ifdef TCC_TARGET_ARM
7404− vpushs(size);
7405− vpushi(0);
7406−#else
74077402 vpushi(0);
74087403 vpushs(size);
7404+#if defined TCC_TARGET_ARM && defined TCC_ARM_EABI
7405+ vswap(); /* using __aeabi_memset(void*, size_t, int) */
74097406 #endif
74107407 gfunc_call(3);
74117408 }
tccpe.c+5−2
@@ -889,7 +889,7 @@ static void pe_build_imports(struct pe_info *pe) · 888 unmodified lines
889889
890890 dllindex = p->dll_index;
891891 if (dllindex)
892− name = tcc_basename((dllref = pe->s1->loaded_dlls[dllindex-1])->name);
892+ name = (dllref = pe->s1->loaded_dlls[dllindex-1])->name;
893893 else
894894 name = "", dllref = NULL;
895895
@@ -1767,6 +1767,9 @@ static int pe_load_def(TCCState *s1, int fd) · 871 unmodified lines
17671767 char dllname[80], *buf, *line, *p, *x, next;
17681768
17691769 buf = tcc_load_text(fd);
1770+ if (!buf)
1771+ return ret;
1772+
17701773 for (line = buf;; ++line) {
17711774 p = get_token(&line, &next);
17721775 if (!(*p && *p != ';'))
@@ -1815,7 +1818,7 @@ quit: · 42 unmodified lines
18151818 static int pe_load_dll(TCCState *s1, int fd, const char *filename)
18161819 {
18171820 char *p, *q;
1818− DLLReference *ref = tcc_add_dllref(s1, filename, 0);
1821+ DLLReference *ref = tcc_add_dllref(s1, tcc_basename(filename), 0);
18191822 if (ref->found)
18201823 return 0;
18211824 if (get_dllexports(fd, &p))
tccpp.c+32−31
@@ -92,7 +92,6 @@ static const unsigned char tok_two_chars[] = · 91 unmodified lines
9292 '-','>', TOK_ARROW,
9393 '.','.', TOK_TWODOTS,
9494 '#','#', TOK_TWOSHARPS,
95− '#','#', TOK_PPJOIN,
9695 0
9796 };
9897
@@ -137,10 +136,8 @@ ST_FUNC void expect(const char *msg) · 38 unmodified lines
137136
138137 #define TOKSYM_TAL_SIZE (768 * 1024) /* allocator for tiny TokenSym in table_ident */
139138 #define TOKSTR_TAL_SIZE (768 * 1024) /* allocator for tiny TokenString instances */
140−#define CSTR_TAL_SIZE (256 * 1024) /* allocator for tiny CString instances */
141−#define TOKSYM_TAL_LIMIT 256 /* prefer unique limits to distinguish allocators debug msgs */
142−#define TOKSTR_TAL_LIMIT 128 /* 32 * sizeof(int) */
143−#define CSTR_TAL_LIMIT 1024
139+#define TOKSYM_TAL_LIMIT 256 /* prefer unique limits to distinguish allocators debug msgs */
140+#define TOKSTR_TAL_LIMIT 1024 /* 256 * sizeof(int) */
144141
145142 typedef struct TinyAlloc {
146143 unsigned limit;
@@ -185,8 +182,8 @@ tail_call: · 38 unmodified lines
185182 if (!al)
186183 return;
187184 #ifdef TAL_INFO
188− fprintf(stderr, "limit=%5d, size=%5g MB, nb_peak=%6d, nb_total=%8d, nb_missed=%6d, usage=%5.1f%%\n",
189− al->limit, al->size / 1024.0 / 1024.0, al->nb_peak, al->nb_total, al->nb_missed,
185+ fprintf(stderr, "limit %4d size %7d nb_peak %5d nb_total %7d nb_missed %5d usage %5.1f%%\n",
186+ al->limit, al->size, al->nb_peak, al->nb_total, al->nb_missed,
190187 (al->peak_p - al->buffer) * 100.0 / al->size);
191188 #endif
192189 #if TAL_DEBUG && TAL_DEBUG != 3 /* do not check TAL leaks with -DMEM_DEBUG=3 */
@@ -345,7 +342,7 @@ ST_INLN void cstr_ccat(CString *cstr, int ch) · 152 unmodified lines
345342 size = cstr->size + 1;
346343 if (size > cstr->size_allocated)
347344 cstr_realloc(cstr, size);
348− ((unsigned char *)cstr->data)[size - 1] = ch;
345+ cstr->data[size - 1] = ch;
349346 cstr->size = size;
350347 }
351348
@@ -368,6 +365,7 @@ ST_INLN void cstr_u8cat(CString *cstr, int ch) · 16 unmodified lines
368365 cstr_cat(cstr, buf, e - buf);
369366 }
370367
368+/* add string of 'len', or of its len/len+1 when 'len' == -1/0 */
371369 ST_FUNC void cstr_cat(CString *cstr, const char *str, int len)
372370 {
373371 int size;
@@ -376,7 +374,7 @@ ST_FUNC void cstr_cat(CString *cstr, const char *str, int len) · 2 unmodified lines
376374 size = cstr->size + len;
377375 if (size > cstr->size_allocated)
378376 cstr_realloc(cstr, size);
379− memmove(((unsigned char *)cstr->data) + cstr->size, str, len);
377+ memmove(cstr->data + cstr->size, str, len);
380378 cstr->size = size;
381379 }
382380
@@ -387,7 +385,7 @@ ST_FUNC void cstr_wccat(CString *cstr, int ch) · 4 unmodified lines
387385 size = cstr->size + sizeof(nwchar_t);
388386 if (size > cstr->size_allocated)
389387 cstr_realloc(cstr, size);
390− *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
388+ *(nwchar_t *)(cstr->data + size - sizeof(nwchar_t)) = ch;
391389 cstr->size = size;
392390 }
393391
@@ -418,7 +416,7 @@ ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap) · 24 unmodified lines
418416 cstr_realloc(cstr, size);
419417 size = cstr->size_allocated - cstr->size;
420418 va_copy(v, ap);
421− len = vsnprintf((char*)cstr->data + cstr->size, size, fmt, v);
419+ len = vsnprintf(cstr->data + cstr->size, size, fmt, v);
422420 va_end(v);
423421 if (len >= 0 && len < size)
424422 break;
@@ -1920,7 +1918,8 @@ ST_FUNC void preprocess(int is_bof) · 1495 unmodified lines
19201918 if (file->fd > 0)
19211919 total_lines += file->line_num - n;
19221920 file->line_num = n;
1923− break;
1921+ goto ignore; /* skip optional level number */
1922+
19241923 case TOK_ERROR:
19251924 case TOK_WARNING:
19261925 q = buf;
@@ -3070,12 +3069,13 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) · 1143 unmodified lines
30703069 /* handle the '##' operator. return the resulting string (which must be freed). */
30713070 static inline int *macro_twosharps(const int *ptr0)
30723071 {
3073− int t1, t2, n;
3072+ int t1, t2, n, l;
30743073 CValue cv1, cv2;
30753074 TokenString macro_str1;
30763075 const int *ptr;
30773076
30783077 tok_str_new(&macro_str1);
3078+ cstr_reset(&tokcstr);
30793079 for (ptr = ptr0;;) {
30803080 TOK_GET(&t1, &ptr, &cv1);
30813081 if (t1 == 0)
@@ -3090,29 +3090,31 @@ static inline int *macro_twosharps(const int *ptr0) · 8 unmodified lines
30903090 while ((t2 = *++ptr) == ' ' || t2 == TOK_PPJOIN)
30913091 ;
30923092 TOK_GET(&t2, &ptr, &cv2);
3093− if (t1 == TOK_PLCHLDR && t2 == TOK_PLCHLDR)
3093+ if (t2 == TOK_PLCHLDR)
30943094 continue;
3095− cstr_reset(&tokcstr);
3096− if (t1 != TOK_PLCHLDR)
3095+ if (t1 != TOK_PLCHLDR) {
30973096 cstr_cat(&tokcstr, get_tok_str(t1, &cv1), -1);
3098− n = tokcstr.size;
3099− if (t2 != TOK_PLCHLDR)
3100− cstr_cat(&tokcstr, get_tok_str(t2, &cv2), -1);
3101− cstr_ccat(&tokcstr, '\0');
3102− //printf("paste <%s>\n", (char*)tokcstr.data);
3097+ t1 = TOK_PLCHLDR;
3098+ }
3099+ cstr_cat(&tokcstr, get_tok_str(t2, &cv2), -1);
3100+ }
3101+ if (tokcstr.size) {
3102+ cstr_ccat(&tokcstr, 0);
31033103 tcc_open_bf(tcc_state, ":paste:", tokcstr.size);
31043104 memcpy(file->buffer, tokcstr.data, tokcstr.size);
31053105 tok_flags = 0; /* don't interpret '#' */
3106− next_nomacro();
3107− if (*file->buf_ptr == 0) {
3108− t1 = tok, cv1 = tokc;
3109− } else {
3106+ for (n = 0;;n = l) {
3107+ next_nomacro();
3108+ tok_str_add2(&macro_str1, tok, &tokc);
3109+ if (*file->buf_ptr == 0)
3110+ break;
3111+ tok_str_add(&macro_str1, ' ');
3112+ l = file->buf_ptr - file->buffer;
31103113 tcc_warning("pasting \"%.*s\" and \"%s\" does not give a valid"
3111− " preprocessing token", n, file->buffer, file->buffer + n);
3112− tok_str_add2(&macro_str1, t1, &cv1);
3113− t1 = t2, cv1 = cv2;
3114+ " preprocessing token", l - n, file->buffer + n, file->buf_ptr);
31143115 }
31153116 tcc_close();
3117+ cstr_reset(&tokcstr);
31163118 }
31173119 if (t1 != TOK_PLCHLDR)
31183120 tok_str_add2(&macro_str1, t1, &cv1);
@@ -3450,9 +3452,8 @@ redo: · 331 unmodified lines
34503452 /* do nothing */
34513453 } else {
34523454 ++macro_ptr;
3453− if (t >= TOK_IDENT) {
3454− t &= ~SYM_FIELD; /* remove 'nosubst' marker */
3455− } else if (t == '\\') {
3455+ t &= ~SYM_FIELD; /* remove 'nosubst' marker */
3456+ if (t == '\\') {
34563457 if (!(parse_flags & PARSE_FLAG_ACCEPT_STRAYS))
34573458 tcc_error("stray '\\' in program");
34583459 }
tests/tests2/60_errors_and_warnings.c+7−0
@@ -483,4 +483,11 @@ struct A { · 482 unmodified lines
483483 # if X(1,2) //undefined function macro
484484 # endif
485485
486+#elif defined test_pointer_plus_double
487+
488+int *invalid_operation(int *p, double d)
489+{
490+ return p + d;
491+}
492+
486493 #endif
tests/tests2/60_errors_and_warnings.expect+3−0
@@ -237,3 +237,6 @@ arg[1] = "Y" · 236 unmodified lines
237237
238238 [test_pp_error_2]
239239 60_errors_and_warnings.c:483: error: bad preprocessor expression: #if 0 ( 1 , 2 )
240+
241+[test_pointer_plus_double]
242+60_errors_and_warnings.c:490: error: invalid operand types for binary operation
tests/thiscall/thiscall-test.c+0−17
@@ -1,17 +0,0 @@
1−#ifndef __thiscall
2− #define __thiscall __attribute__((thiscall))
3−#endif
4−#ifndef __cdecl
5− #define __cdecl __attribute__((cdecl))
6−#endif
7−#ifndef __stdcall
8− #define __stdcall __attribute__((stdcall))
9−#endif
10−
11−void ( __thiscall * const thisCall1 ) ( void * _this, int a ) = ( void ( __thiscall * ) ( void * _this, int a ) ) 0x4788a0;
12−
13−int main() {
14− thisCall1((void*) 0xDEADBEEF, 1000);
15−
16− return 1;
17−}
x86_64-link.c+3−3
@@ -25,7 +25,7 @@ · 24 unmodified lines
2525 #ifdef NEED_RELOC_TYPE
2626 /* Returns 1 for a code relocation, 0 for a data relocation. For unknown
2727 relocations, returns -1. */
28−int code_reloc (int reloc_type)
28+ST_FUNC int code_reloc (int reloc_type)
2929 {
3030 switch (reloc_type) {
3131 case R_X86_64_32:
@@ -64,7 +64,7 @@ int code_reloc (int reloc_type) · 32 unmodified lines
6464 /* Returns an enumerator to describe whether and when the relocation needs a
6565 GOT and/or PLT entry to be created. See tcc.h for a description of the
6666 different values. */
67−int gotplt_entry_type (int reloc_type)
67+ST_FUNC int gotplt_entry_type (int reloc_type)
6868 {
6969 switch (reloc_type) {
7070 case R_X86_64_GLOB_DAT:
@@ -186,7 +186,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 115 unmodified lines
186186 #endif
187187 #endif
188188
189−void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
189+ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
190190 {
191191 int sym_index, esym_index;
192192

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t