- 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
Unified · Split
| @@ -198,6 +198,7 @@ DEFINES += $(if $(ELF-$T),-DCONFIG_TCC_ELFINTERP="\"$(ELF-$T)\"") · 197 unmodified lines | ||
| 198 | 198 | DEFINES += $(DEF-$(or $(findstring win,$T),unx)) |
| 199 | 199 | |
| 200 | 200 | ifneq ($(X),) |
| 201 | +$(if $(DEF-$T),,$(error error: unknown target: '$T')) | |
| 201 | 202 | DEF-all += -DCONFIG_TCC_CROSSPREFIX="\"$X\"" |
| 202 | 203 | ifneq ($(CONFIG_WIN32),yes) |
| 203 | 204 | DEF-win += -DCONFIG_TCCDIR="\"$(tccdir)/win32\"" |
| @@ -92,7 +92,6 @@ static void parse_operand(TCCState *s1, Operand *op) · 91 unmodified lines | ||
| 92 | 92 | reg = asm_parse_regvar(tok); |
| 93 | 93 | if (reg == -1) { |
| 94 | 94 | expect("register"); |
| 95 | − return; | |
| 96 | 95 | } else |
| 97 | 96 | next(); // skip register name |
| 98 | 97 | |
| @@ -103,9 +102,7 @@ static void parse_operand(TCCState *s1, Operand *op) · 4 unmodified lines | ||
| 103 | 102 | break; |
| 104 | 103 | next(); // skip ',' |
| 105 | 104 | } |
| 106 | − if (tok != '}') | |
| 107 | − expect("'}'"); | |
| 108 | − next(); // skip '}' | |
| 105 | + skip('}'); | |
| 109 | 106 | if (regset == 0) { |
| 110 | 107 | // ARM instructions don't support empty regset. |
| 111 | 108 | tcc_error("empty register list is not supported"); |
| @@ -186,7 +183,6 @@ ST_FUNC void gen_expr32(ExprValue *pe) · 74 unmodified lines | ||
| 186 | 183 | static uint32_t condition_code_of_token(int token) { |
| 187 | 184 | if (token < TOK_ASM_nopeq) { |
| 188 | 185 | expect("condition-enabled instruction"); |
| 189 | − return 0; | |
| 190 | 186 | } else |
| 191 | 187 | return (token - TOK_ASM_nopeq) & 15; |
| 192 | 188 | } |
| @@ -262,19 +258,14 @@ static void asm_binary_opcode(TCCState *s1, int token) · 69 unmodified lines | ||
| 262 | 258 | uint32_t encoded_rotation = 0; |
| 263 | 259 | uint64_t amount; |
| 264 | 260 | parse_operand(s1, &ops[0]); |
| 265 | − if (tok == ',') | |
| 266 | − next(); | |
| 267 | − else | |
| 268 | − expect("','"); | |
| 261 | + skip(','); | |
| 269 | 262 | parse_operand(s1, &ops[1]); |
| 270 | 263 | if (ops[0].type != OP_REG32) { |
| 271 | 264 | expect("(destination operand) register"); |
| 272 | − return; | |
| 273 | 265 | } |
| 274 | 266 | |
| 275 | 267 | if (ops[0].reg == 15) { |
| 276 | 268 | tcc_error("'%s' does not support 'pc' as operand", get_tok_str(token, NULL)); |
| 277 | − return; | |
| 278 | 269 | } |
| 279 | 270 | |
| 280 | 271 | if (ops[0].reg == 13) |
| @@ -308,7 +299,6 @@ static void asm_binary_opcode(TCCState *s1, int token) · 27 unmodified lines | ||
| 308 | 299 | |
| 309 | 300 | if (ops[1].reg == 15) { |
| 310 | 301 | tcc_error("'%s' does not support 'pc' as operand", get_tok_str(token, NULL)); |
| 311 | − return; | |
| 312 | 302 | } |
| 313 | 303 | |
| 314 | 304 | if (ops[1].reg == 13) |
| @@ -321,7 +311,6 @@ static void asm_binary_opcode(TCCState *s1, int token) · 6 unmodified lines | ||
| 321 | 311 | parse_operand(s1, &rotation); |
| 322 | 312 | if (rotation.type != OP_IM8) { |
| 323 | 313 | expect("immediate value for rotation"); |
| 324 | − return; | |
| 325 | 314 | } else { |
| 326 | 315 | amount = rotation.e.v; |
| 327 | 316 | switch (amount) { |
| @@ -336,7 +325,6 @@ static void asm_binary_opcode(TCCState *s1, int token) · 8 unmodified lines | ||
| 336 | 325 | break; |
| 337 | 326 | default: |
| 338 | 327 | expect("'8' or '16' or '24'"); |
| 339 | − return; | |
| 340 | 328 | } |
| 341 | 329 | } |
| 342 | 330 | } |
| @@ -378,32 +366,21 @@ static void asm_coprocessor_opcode(TCCState *s1, int token) { · 35 unmodified lines | ||
| 378 | 366 | next(); |
| 379 | 367 | } else { |
| 380 | 368 | expect("'p<number>'"); |
| 381 | − return; | |
| 382 | 369 | } |
| 383 | − | |
| 384 | − if (tok == ',') | |
| 385 | − next(); | |
| 386 | − else | |
| 387 | − expect("','"); | |
| 388 | − | |
| 370 | + skip(','); | |
| 389 | 371 | parse_operand(s1, &opcode1); |
| 390 | 372 | if (opcode1.type != OP_IM8 || opcode1.e.v > 15) { |
| 391 | 373 | tcc_error("opcode1 of instruction '%s' must be an immediate value between 0 and 15", get_tok_str(token, NULL)); |
| 392 | − return; | |
| 393 | 374 | } |
| 394 | 375 | |
| 395 | 376 | for (i = 0; i < 3; ++i) { |
| 396 | − if (tok == ',') | |
| 397 | − next(); | |
| 398 | − else | |
| 399 | − expect("','"); | |
| 377 | + skip(','); | |
| 400 | 378 | if (i == 0 && token != TOK_ASM_cdp2 && (ARM_INSTRUCTION_GROUP(token) == TOK_ASM_mrceq || ARM_INSTRUCTION_GROUP(token) == TOK_ASM_mcreq)) { |
| 401 | 379 | if (tok >= TOK_ASM_r0 && tok <= TOK_ASM_r15) { |
| 402 | 380 | registers[i] = tok - TOK_ASM_r0; |
| 403 | 381 | next(); |
| 404 | 382 | } else { |
| 405 | 383 | expect("'r<number>'"); |
| 406 | − return; | |
| 407 | 384 | } |
| 408 | 385 | } else { |
| 409 | 386 | 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 | ||
| 411 | 388 | next(); |
| 412 | 389 | } else { |
| 413 | 390 | expect("'c<number>'"); |
| 414 | − return; | |
| 415 | 391 | } |
| 416 | 392 | } |
| 417 | 393 | } |
| @@ -424,7 +400,6 @@ static void asm_coprocessor_opcode(TCCState *s1, int token) { · 6 unmodified lines | ||
| 424 | 400 | } |
| 425 | 401 | if (opcode2.type != OP_IM8 || opcode2.e.v > 15) { |
| 426 | 402 | tcc_error("opcode2 of instruction '%s' must be an immediate value between 0 and 15", get_tok_str(token, NULL)); |
| 427 | − return; | |
| 428 | 403 | } |
| 429 | 404 | |
| 430 | 405 | if (token == TOK_ASM_cdp2) { |
| @@ -446,7 +421,6 @@ static void asm_coprocessor_opcode(TCCState *s1, int token) { · 15 unmodified lines | ||
| 446 | 421 | // opcode1 encoding changes! highest and lowest bit gone. |
| 447 | 422 | if (opcode1.e.v > 7) { |
| 448 | 423 | tcc_error("opcode1 of instruction '%s' must be an immediate value between 0 and 7", get_tok_str(token, NULL)); |
| 449 | − return; | |
| 450 | 424 | } |
| 451 | 425 | asm_emit_coprocessor_opcode(high_nibble, coprocessor, (opcode1.e.v << 1) | mrc, registers[0], registers[1], registers[2], opcode2.e.v, 1); |
| 452 | 426 | break; |
| @@ -490,10 +464,8 @@ static void asm_block_data_transfer_opcode(TCCState *s1, int token) · 37 unmodified lines | ||
| 490 | 464 | } |
| 491 | 465 | if (nb_ops < 1) { |
| 492 | 466 | expect("at least one operand"); |
| 493 | − return; | |
| 494 | 467 | } else if (ops[nb_ops - 1].type != OP_REGSET32) { |
| 495 | 468 | expect("(last operand) register list"); |
| 496 | − return; | |
| 497 | 469 | } |
| 498 | 470 | |
| 499 | 471 | // 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 | ||
| 683 | 655 | } else if (nb_ops == 3) { |
| 684 | 656 | 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 |
| 685 | 657 | tcc_error("'%s' cannot be used with three operands", get_tok_str(token, NULL)); |
| 686 | − return; | |
| 687 | 658 | } |
| 688 | 659 | } |
| 689 | 660 | if (nb_ops != 3) { |
| 690 | 661 | expect("two or three operands"); |
| 691 | − return; | |
| 692 | 662 | } else { |
| 693 | 663 | uint32_t opcode = 0; |
| 694 | 664 | uint32_t immediate_value; |
| @@ -697,7 +667,6 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 2 unmodified lines | ||
| 697 | 667 | if ((ops[0].type == OP_REG32 && ops[0].reg == 15) || |
| 698 | 668 | (ops[1].type == OP_REG32 && ops[1].reg == 15)) { |
| 699 | 669 | tcc_error("Using the 'pc' register in data processing instructions that have a register-controlled shift is not implemented by ARM"); |
| 700 | − return; | |
| 701 | 670 | } |
| 702 | 671 | } |
| 703 | 672 | |
| @@ -806,7 +775,6 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 102 unmodified lines | ||
| 806 | 775 | if (half_immediate_rotation >= 16) { |
| 807 | 776 | immediate_value = ops[2].e.v; |
| 808 | 777 | tcc_error("immediate value 0x%X cannot be encoded into ARM immediate", (unsigned) immediate_value); |
| 809 | − return; | |
| 810 | 778 | } |
| 811 | 779 | operands |= immediate_value; |
| 812 | 780 | operands |= half_immediate_rotation << 8; |
| @@ -846,12 +814,10 @@ static void asm_shift_opcode(TCCState *s1, int token) · 33 unmodified lines | ||
| 846 | 814 | } |
| 847 | 815 | if (nb_ops < 2) { |
| 848 | 816 | expect("at least two operands"); |
| 849 | − return; | |
| 850 | 817 | } |
| 851 | 818 | |
| 852 | 819 | if (ops[0].type != OP_REG32) { |
| 853 | 820 | expect("(destination operand) register"); |
| 854 | − return; | |
| 855 | 821 | } else |
| 856 | 822 | operands |= ENCODE_RD(ops[0].reg); |
| 857 | 823 | |
| @@ -876,7 +842,6 @@ static void asm_shift_opcode(TCCState *s1, int token) · 18 unmodified lines | ||
| 876 | 842 | } |
| 877 | 843 | if (nb_ops != 3) { |
| 878 | 844 | expect("two or three operands"); |
| 879 | − return; | |
| 880 | 845 | } |
| 881 | 846 | |
| 882 | 847 | switch (ARM_INSTRUCTION_GROUP(token)) { |
| @@ -896,7 +861,6 @@ static void asm_shift_opcode(TCCState *s1, int token) · 13 unmodified lines | ||
| 896 | 861 | operands |= ENCODE_IMMEDIATE_FLAG; |
| 897 | 862 | operands |= ops[1].e.v; |
| 898 | 863 | 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; | |
| 900 | 864 | } |
| 901 | 865 | |
| 902 | 866 | switch (ops[2].type) { |
| @@ -934,7 +898,6 @@ static void asm_shift_opcode(TCCState *s1, int token) · 31 unmodified lines | ||
| 934 | 898 | break; |
| 935 | 899 | default: |
| 936 | 900 | expect("shift instruction"); |
| 937 | − return; | |
| 938 | 901 | } |
| 939 | 902 | asm_emit_opcode(token, opcode | operands); |
| 940 | 903 | } |
| @@ -963,7 +926,6 @@ static void asm_multiplication_opcode(TCCState *s1, int token) · 22 unmodified lines | ||
| 963 | 926 | break; |
| 964 | 927 | default: |
| 965 | 928 | expect("at least three operands"); |
| 966 | − return; | |
| 967 | 929 | } |
| 968 | 930 | nb_ops = 3; |
| 969 | 931 | } |
| @@ -1037,7 +999,6 @@ static void asm_long_multiplication_opcode(TCCState *s1, int token) · 67 unmodified lines | ||
| 1037 | 999 | } |
| 1038 | 1000 | if (nb_ops != 4) { |
| 1039 | 1001 | expect("four operands"); |
| 1040 | − return; | |
| 1041 | 1002 | } |
| 1042 | 1003 | |
| 1043 | 1004 | // long multiply (special case): |
| @@ -1117,12 +1078,10 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 73 unmodified lines | ||
| 1117 | 1078 | opcode |= ENCODE_RD(ops[0].reg); |
| 1118 | 1079 | else { |
| 1119 | 1080 | expect("(destination operand) register"); |
| 1120 | − return; | |
| 1121 | 1081 | } |
| 1122 | 1082 | if (tok != ',') |
| 1123 | 1083 | expect("at least two arguments"); |
| 1124 | − else | |
| 1125 | − next(); // skip ',' | |
| 1084 | + next(); // skip ',' | |
| 1126 | 1085 | |
| 1127 | 1086 | switch (ARM_INSTRUCTION_GROUP(token)) { |
| 1128 | 1087 | case TOK_ASM_strexbeq: |
| @@ -1130,7 +1089,6 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 1 unmodified line | ||
| 1130 | 1089 | parse_operand(s1, &strex_operand); |
| 1131 | 1090 | if (strex_operand.type != OP_REG32) { |
| 1132 | 1091 | expect("register"); |
| 1133 | − return; | |
| 1134 | 1092 | } |
| 1135 | 1093 | if (tok != ',') |
| 1136 | 1094 | expect("at least three arguments"); |
| @@ -1139,17 +1097,12 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 2 unmodified lines | ||
| 1139 | 1097 | break; |
| 1140 | 1098 | } |
| 1141 | 1099 | |
| 1142 | − if (tok != '[') | |
| 1143 | − expect("'['"); | |
| 1144 | − else | |
| 1145 | − next(); // skip '[' | |
| 1146 | − | |
| 1100 | + skip('['); | |
| 1147 | 1101 | parse_operand(s1, &ops[1]); |
| 1148 | 1102 | if (ops[1].type == OP_REG32) |
| 1149 | 1103 | opcode |= ENCODE_RN(ops[1].reg); |
| 1150 | 1104 | else { |
| 1151 | 1105 | expect("(first source operand) register"); |
| 1152 | − return; | |
| 1153 | 1106 | } |
| 1154 | 1107 | if (tok == ']') { |
| 1155 | 1108 | next(); |
| @@ -1166,7 +1119,6 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 10 unmodified lines | ||
| 1166 | 1119 | if (ops[2].type == OP_REG32) { |
| 1167 | 1120 | if (ops[2].reg == 15) { |
| 1168 | 1121 | tcc_error("Using 'pc' for register offset in '%s' is not implemented by ARM", get_tok_str(token, NULL)); |
| 1169 | − return; | |
| 1170 | 1122 | } |
| 1171 | 1123 | if (tok == ',') { |
| 1172 | 1124 | next(); |
| @@ -1182,10 +1134,7 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 9 unmodified lines | ||
| 1182 | 1134 | opcode |= 1 << 24; // add offset before transfer |
| 1183 | 1135 | } |
| 1184 | 1136 | if (!closed_bracket) { |
| 1185 | − if (tok != ']') | |
| 1186 | − expect("']'"); | |
| 1187 | − else | |
| 1188 | − next(); // skip ']' | |
| 1137 | + skip(']'); | |
| 1189 | 1138 | opcode |= 1 << 24; // add offset before transfer |
| 1190 | 1139 | if (tok == '!') { |
| 1191 | 1140 | exclam = 1; |
| @@ -1257,14 +1206,11 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 65 unmodified lines | ||
| 1257 | 1206 | case TOK_ASM_strexeq: |
| 1258 | 1207 | if ((opcode & 0xFFF) || nb_shift) { |
| 1259 | 1208 | tcc_error("neither offset nor shift allowed with 'strex'"); |
| 1260 | − return; | |
| 1261 | 1209 | } else if (opcode & ENCODE_IMMEDIATE_FLAG) { // if set, it means it's NOT immediate |
| 1262 | 1210 | tcc_error("offset not allowed with 'strex'"); |
| 1263 | − return; | |
| 1264 | 1211 | } |
| 1265 | 1212 | if ((opcode & (1 << 24)) == 0) { // add offset after transfer |
| 1266 | 1213 | tcc_error("adding offset after transfer not allowed with 'strex'"); |
| 1267 | − return; | |
| 1268 | 1214 | } |
| 1269 | 1215 | |
| 1270 | 1216 | 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 | ||
| 1277 | 1223 | case TOK_ASM_ldrexeq: |
| 1278 | 1224 | if ((opcode & 0xFFF) || nb_shift) { |
| 1279 | 1225 | tcc_error("neither offset nor shift allowed with 'ldrex'"); |
| 1280 | − return; | |
| 1281 | 1226 | } else if (opcode & ENCODE_IMMEDIATE_FLAG) { // if set, it means it's NOT immediate |
| 1282 | 1227 | tcc_error("offset not allowed with 'ldrex'"); |
| 1283 | − return; | |
| 1284 | 1228 | } |
| 1285 | 1229 | if ((opcode & (1 << 24)) == 0) { // add offset after transfer |
| 1286 | 1230 | tcc_error("adding offset after transfer not allowed with 'ldrex'"); |
| 1287 | − return; | |
| 1288 | 1231 | } |
| 1289 | 1232 | opcode |= 1 << 20; // L |
| 1290 | 1233 | opcode |= 0x00f; |
| @@ -1313,10 +1256,9 @@ static void asm_emit_coprocessor_data_transfer(uint32_t high_nibble, uint8_t cp_ · 22 unmodified lines | ||
| 1313 | 1256 | //assert(CRd < 16); |
| 1314 | 1257 | opcode |= ENCODE_RD(CRd); |
| 1315 | 1258 | |
| 1316 | − if (Rn->type != OP_REG32) { | |
| 1259 | + if (Rn->type != OP_REG32) | |
| 1317 | 1260 | expect("register"); |
| 1318 | − return; | |
| 1319 | − } | |
| 1261 | + | |
| 1320 | 1262 | //assert(Rn->reg < 16); |
| 1321 | 1263 | opcode |= ENCODE_RN(Rn->reg); |
| 1322 | 1264 | if (preincrement) |
| @@ -1335,12 +1277,10 @@ static void asm_emit_coprocessor_data_transfer(uint32_t high_nibble, uint8_t cp_ · 12 unmodified lines | ||
| 1335 | 1277 | opcode |= 1 << 23; // up |
| 1336 | 1278 | if (v & 3) { |
| 1337 | 1279 | tcc_error("immediate offset must be a multiple of 4"); |
| 1338 | − return; | |
| 1339 | 1280 | } |
| 1340 | 1281 | v >>= 2; |
| 1341 | 1282 | if (v > 255) { |
| 1342 | 1283 | tcc_error("immediate offset must be between -1020 and 1020"); |
| 1343 | − return; | |
| 1344 | 1284 | } |
| 1345 | 1285 | opcode |= v; |
| 1346 | 1286 | } 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 | ||
| 1349 | 1289 | opcode |= ENCODE_IMMEDIATE_FLAG; /* if set, it means it's NOT immediate */ |
| 1350 | 1290 | opcode |= offset->reg; |
| 1351 | 1291 | tcc_error("Using register offset to register address is not possible here"); |
| 1352 | − return; | |
| 1353 | 1292 | } else if (offset->type == OP_VREG64) { |
| 1354 | 1293 | opcode |= 16; |
| 1355 | 1294 | opcode |= offset->reg; |
| @@ -1380,36 +1319,22 @@ static void asm_coprocessor_data_transfer_opcode(TCCState *s1, int token) · 24 unmodified lines | ||
| 1380 | 1319 | next(); |
| 1381 | 1320 | } else { |
| 1382 | 1321 | expect("'c<number>'"); |
| 1383 | − return; | |
| 1384 | 1322 | } |
| 1385 | 1323 | |
| 1386 | − if (tok == ',') | |
| 1387 | − next(); | |
| 1388 | − else | |
| 1389 | − expect("','"); | |
| 1324 | + skip(','); | |
| 1390 | 1325 | |
| 1391 | 1326 | if (tok >= TOK_ASM_c0 && tok <= TOK_ASM_c15) { |
| 1392 | 1327 | coprocessor_destination_register = tok - TOK_ASM_c0; |
| 1393 | 1328 | next(); |
| 1394 | 1329 | } else { |
| 1395 | 1330 | expect("'c<number>'"); |
| 1396 | − return; | |
| 1397 | 1331 | } |
| 1398 | 1332 | |
| 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('['); | |
| 1409 | 1335 | parse_operand(s1, &ops[1]); |
| 1410 | 1336 | if (ops[1].type != OP_REG32) { |
| 1411 | 1337 | expect("(first source operand) register"); |
| 1412 | − return; | |
| 1413 | 1338 | } |
| 1414 | 1339 | if (tok == ']') { |
| 1415 | 1340 | next(); |
| @@ -1426,11 +1351,9 @@ static void asm_coprocessor_data_transfer_opcode(TCCState *s1, int token) · 10 unmodified lines | ||
| 1426 | 1351 | if (ops[2].type == OP_REG32) { |
| 1427 | 1352 | if (ops[2].reg == 15) { |
| 1428 | 1353 | tcc_error("Using 'pc' for register offset in '%s' is not implemented by ARM", get_tok_str(token, NULL)); |
| 1429 | − return; | |
| 1430 | 1354 | } |
| 1431 | 1355 | } else if (ops[2].type == OP_VREG64) { |
| 1432 | 1356 | tcc_error("'%s' does not support VFP register operand", get_tok_str(token, NULL)); |
| 1433 | − return; | |
| 1434 | 1357 | } |
| 1435 | 1358 | } else { |
| 1436 | 1359 | // 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 | ||
| 1439 | 1362 | preincrement = 1; // add offset before transfer |
| 1440 | 1363 | } |
| 1441 | 1364 | if (!closed_bracket) { |
| 1442 | − if (tok != ']') | |
| 1443 | − expect("']'"); | |
| 1444 | − else | |
| 1445 | − next(); // skip ']' | |
| 1365 | + skip(']'); | |
| 1446 | 1366 | preincrement = 1; // add offset before transfer |
| 1447 | 1367 | if (tok == '!') { |
| 1448 | 1368 | exclam = 1; |
| @@ -1511,40 +1431,26 @@ static void asm_floating_point_single_data_transfer_opcode(TCCState *s1, int tok · 62 unmodified lines | ||
| 1511 | 1431 | next(); |
| 1512 | 1432 | } else { |
| 1513 | 1433 | expect("floating point register"); |
| 1514 | − return; | |
| 1515 | 1434 | } |
| 1516 | 1435 | |
| 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('['); | |
| 1527 | 1438 | parse_operand(s1, &ops[1]); |
| 1528 | 1439 | if (ops[1].type != OP_REG32) { |
| 1529 | 1440 | expect("(first source operand) register"); |
| 1530 | − return; | |
| 1531 | 1441 | } |
| 1532 | 1442 | if (tok == ',') { |
| 1533 | 1443 | next(); // skip ',' |
| 1534 | 1444 | parse_operand(s1, &ops[2]); |
| 1535 | 1445 | if (ops[2].type != OP_IM8 && ops[2].type != OP_IM8N) { |
| 1536 | 1446 | expect("immediate offset"); |
| 1537 | − return; | |
| 1538 | 1447 | } |
| 1539 | 1448 | } else { |
| 1540 | 1449 | // end of input expression in brackets--assume 0 offset |
| 1541 | 1450 | ops[2].type = OP_IM8; |
| 1542 | 1451 | ops[2].e.v = 0; |
| 1543 | 1452 | } |
| 1544 | − if (tok != ']') | |
| 1545 | − expect("']'"); | |
| 1546 | − else | |
| 1547 | − next(); // skip ']' | |
| 1453 | + skip(']'); | |
| 1548 | 1454 | |
| 1549 | 1455 | switch (ARM_INSTRUCTION_GROUP(token)) { |
| 1550 | 1456 | case TOK_ASM_vldreq: |
| @@ -1583,19 +1489,10 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *s1, int toke · 32 unmodified lines | ||
| 1583 | 1489 | op0_exclam = 1; |
| 1584 | 1490 | next(); // skip '!' |
| 1585 | 1491 | } |
| 1586 | − if (tok == ',') | |
| 1587 | − next(); // skip comma | |
| 1588 | − else { | |
| 1589 | − expect("','"); | |
| 1590 | − return; | |
| 1591 | − } | |
| 1492 | + skip(','); | |
| 1592 | 1493 | } |
| 1593 | 1494 | |
| 1594 | − if (tok != '{') { | |
| 1595 | − expect("'{'"); | |
| 1596 | − return; | |
| 1597 | − } | |
| 1598 | − next(); // skip '{' | |
| 1495 | + skip('{'); | |
| 1599 | 1496 | first_regset_register = asm_parse_vfp_regvar(tok, 1); |
| 1600 | 1497 | if ((first_regset_register = asm_parse_vfp_regvar(tok, 1)) != -1) { |
| 1601 | 1498 | 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 | ||
| 1605 | 1502 | next(); |
| 1606 | 1503 | } else { |
| 1607 | 1504 | expect("floating-point register"); |
| 1608 | − return; | |
| 1609 | 1505 | } |
| 1610 | 1506 | |
| 1611 | 1507 | if (tok == '-') { |
| @@ -1614,21 +1510,14 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *s1, int toke · 2 unmodified lines | ||
| 1614 | 1510 | next(); |
| 1615 | 1511 | else { |
| 1616 | 1512 | expect("floating-point register"); |
| 1617 | − return; | |
| 1618 | 1513 | } |
| 1619 | 1514 | } else |
| 1620 | 1515 | last_regset_register = first_regset_register; |
| 1621 | 1516 | |
| 1622 | 1517 | if (last_regset_register < first_regset_register) { |
| 1623 | 1518 | 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; | |
| 1629 | 1519 | } |
| 1630 | − next(); // skip '}' | |
| 1631 | − | |
| 1520 | + skip('}'); | |
| 1632 | 1521 | // Note: 0 (one down) is not implemented by us regardless. |
| 1633 | 1522 | regset_item_count = last_regset_register - first_regset_register + 1; |
| 1634 | 1523 | 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 | ||
| 1659 | 1548 | break; |
| 1660 | 1549 | default: |
| 1661 | 1550 | expect("floating point block data transfer instruction"); |
| 1662 | − return; | |
| 1663 | 1551 | } |
| 1664 | 1552 | if (ops[0].type != OP_REG32) |
| 1665 | 1553 | expect("(first operand) register"); |
| @@ -1713,7 +1601,6 @@ static uint32_t vmov_parse_immediate_value() { · 47 unmodified lines | ||
| 1713 | 1601 | |
| 1714 | 1602 | if (tok != TOK_PPNUM) { |
| 1715 | 1603 | expect("immediate value"); |
| 1716 | − return 0; | |
| 1717 | 1604 | } |
| 1718 | 1605 | p = tokc.str.data; |
| 1719 | 1606 | errno = 0; |
| @@ -1721,7 +1608,6 @@ static uint32_t vmov_parse_immediate_value() { · 1 unmodified line | ||
| 1721 | 1608 | |
| 1722 | 1609 | if (errno || integral_value >= 32) { |
| 1723 | 1610 | tcc_error("invalid floating-point immediate value"); |
| 1724 | − return 0; | |
| 1725 | 1611 | } |
| 1726 | 1612 | |
| 1727 | 1613 | value = (uint32_t) integral_value * VMOV_ONE; |
| @@ -1754,7 +1640,6 @@ static uint8_t vmov_encode_immediate_value(uint32_t value) · 26 unmodified lines | ||
| 1754 | 1640 | } |
| 1755 | 1641 | if (r == -1 || value < beginning || value > end) { |
| 1756 | 1642 | tcc_error("invalid decimal number for vmov: %d", value); |
| 1757 | − return 0; | |
| 1758 | 1643 | } |
| 1759 | 1644 | n = vmov_linear_approx_index(beginning, end, value); |
| 1760 | 1645 | 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 | ||
| 1788 | 1673 | operands[1] = 5; |
| 1789 | 1674 | if (immediate_value) { |
| 1790 | 1675 | expect("Immediate value 0"); |
| 1791 | − return; | |
| 1792 | 1676 | } |
| 1793 | 1677 | break; |
| 1794 | 1678 | case TOK_ASM_vcmpeeq_f32: |
| @@ -1797,7 +1681,6 @@ static void asm_floating_point_immediate_data_processing_opcode_tail(TCCState *s · 2 unmodified lines | ||
| 1797 | 1681 | operands[1] = 5; |
| 1798 | 1682 | if (immediate_value) { |
| 1799 | 1683 | expect("Immediate value 0"); |
| 1800 | − return; | |
| 1801 | 1684 | } |
| 1802 | 1685 | break; |
| 1803 | 1686 | case TOK_ASM_vmoveq_f32: |
| @@ -1813,7 +1696,6 @@ static void asm_floating_point_immediate_data_processing_opcode_tail(TCCState *s · 9 unmodified lines | ||
| 1813 | 1696 | break; |
| 1814 | 1697 | default: |
| 1815 | 1698 | expect("known floating point with immediate instruction"); |
| 1816 | − return; | |
| 1817 | 1699 | } |
| 1818 | 1700 | |
| 1819 | 1701 | 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 | ||
| 1833 | 1715 | // "vmov.f32 r2, s3" or "vmov.f32 s3, r2" |
| 1834 | 1716 | if (nb_ops != 2 || nb_arm_regs != 1) { |
| 1835 | 1717 | tcc_error("vmov.f32 only implemented for one VFP register operand and one ARM register operands"); |
| 1836 | − return; | |
| 1837 | 1718 | } |
| 1838 | 1719 | if (ops[0].type != OP_REG32) { // determine mode: load or store |
| 1839 | 1720 | // 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 | ||
| 1860 | 1741 | case CP_DOUBLE_PRECISION_FLOAT: |
| 1861 | 1742 | if (nb_ops != 3 || nb_arm_regs != 2) { |
| 1862 | 1743 | tcc_error("vmov.f32 only implemented for one VFP register operand and two ARM register operands"); |
| 1863 | − return; | |
| 1864 | 1744 | } |
| 1865 | 1745 | // Determine whether it's a store into a VFP register (vmov "d1, r2, r3") rather than "vmov r2, r3, d1" |
| 1866 | 1746 | 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 | ||
| 1873 | 1753 | memcpy(&ops[2], &temp, sizeof(ops[2])); |
| 1874 | 1754 | } else { |
| 1875 | 1755 | tcc_error("vmov.f64 only implemented for one VFP register operand and two ARM register operands"); |
| 1876 | − return; | |
| 1877 | 1756 | } |
| 1878 | 1757 | } else if (ops[0].type != OP_REG32 || ops[1].type != OP_REG32 || ops[2].type != OP_VREG64) { |
| 1879 | 1758 | tcc_error("vmov.f64 only implemented for one VFP register operand and two ARM register operands"); |
| 1880 | − return; | |
| 1881 | 1759 | } else { |
| 1882 | 1760 | opcode1 |= 1; |
| 1883 | 1761 | } |
| @@ -1915,7 +1793,6 @@ static void asm_floating_point_vcvt_data_processing_opcode(TCCState *s1, int tok · 31 unmodified lines | ||
| 1915 | 1793 | break; |
| 1916 | 1794 | default: |
| 1917 | 1795 | tcc_error("Unknown coprocessor for instruction '%s'", get_tok_str(token, NULL)); |
| 1918 | − return; | |
| 1919 | 1796 | } |
| 1920 | 1797 | |
| 1921 | 1798 | 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 | ||
| 1942 | 1819 | break; |
| 1943 | 1820 | } |
| 1944 | 1821 | |
| 1945 | − if (tok == ',') | |
| 1946 | − next(); | |
| 1947 | − else | |
| 1948 | − expect("','"); | |
| 1822 | + skip(','); | |
| 1949 | 1823 | parse_operand(s1, &ops[2]); |
| 1950 | 1824 | |
| 1951 | 1825 | 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 | ||
| 1977 | 1851 | if (ops[0].type == OP_VREG64 && ops[2].type == OP_VREG32) { |
| 1978 | 1852 | } else { |
| 1979 | 1853 | expect("d<number>, s<number>"); |
| 1980 | − return; | |
| 1981 | 1854 | } |
| 1982 | 1855 | break; |
| 1983 | 1856 | default: |
| @@ -1985,13 +1858,11 @@ static void asm_floating_point_vcvt_data_processing_opcode(TCCState *s1, int tok · 1 unmodified line | ||
| 1985 | 1858 | if (ops[0].type == OP_VREG32 && ops[2].type == OP_VREG32) { |
| 1986 | 1859 | } else { |
| 1987 | 1860 | expect("s<number>, s<number>"); |
| 1988 | − return; | |
| 1989 | 1861 | } |
| 1990 | 1862 | } else if (coprocessor == CP_DOUBLE_PRECISION_FLOAT) { |
| 1991 | 1863 | if (ops[0].type == OP_VREG32 && ops[2].type == OP_VREG64) { |
| 1992 | 1864 | } else { |
| 1993 | 1865 | expect("s<number>, d<number>"); |
| 1994 | − return; | |
| 1995 | 1866 | } |
| 1996 | 1867 | } |
| 1997 | 1868 | } |
| @@ -2074,16 +1945,13 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 76 unmodified lines | ||
| 2074 | 1945 | } else if (ops[nb_ops].type == OP_VREG32) { |
| 2075 | 1946 | if (coprocessor != CP_SINGLE_PRECISION_FLOAT) { |
| 2076 | 1947 | expect("'s<number>'"); |
| 2077 | − return; | |
| 2078 | 1948 | } |
| 2079 | 1949 | } else if (ops[nb_ops].type == OP_VREG64) { |
| 2080 | 1950 | if (coprocessor != CP_DOUBLE_PRECISION_FLOAT) { |
| 2081 | 1951 | expect("'d<number>'"); |
| 2082 | − return; | |
| 2083 | 1952 | } |
| 2084 | 1953 | } else { |
| 2085 | 1954 | expect("floating point register"); |
| 2086 | − return; | |
| 2087 | 1955 | } |
| 2088 | 1956 | ++nb_ops; |
| 2089 | 1957 | if (tok == ',') |
| @@ -2100,7 +1968,6 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 10 unmodified lines | ||
| 2100 | 1968 | } |
| 2101 | 1969 | if (nb_ops < 3) { |
| 2102 | 1970 | tcc_error("Not enough operands for '%s' (%u)", get_tok_str(token, NULL), nb_ops); |
| 2103 | − return; | |
| 2104 | 1971 | } |
| 2105 | 1972 | } |
| 2106 | 1973 | |
| @@ -2199,7 +2066,6 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 92 unmodified lines | ||
| 2199 | 2066 | break; |
| 2200 | 2067 | default: |
| 2201 | 2068 | expect("known floating point instruction"); |
| 2202 | − return; | |
| 2203 | 2069 | } |
| 2204 | 2070 | |
| 2205 | 2071 | 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 | ||
| 2256 | 2122 | parse_operand(s1, &arm_operand); |
| 2257 | 2123 | if (arm_operand.type == OP_REG32 && arm_operand.reg == 15) { |
| 2258 | 2124 | tcc_error("'%s' does not support 'pc' as operand", get_tok_str(token, NULL)); |
| 2259 | − return; | |
| 2260 | 2125 | } |
| 2261 | 2126 | } |
| 2262 | 2127 | |
| 2263 | − if (tok != ',') | |
| 2264 | − expect("','"); | |
| 2265 | − else | |
| 2266 | − next(); // skip ',' | |
| 2128 | + skip(','); | |
| 2267 | 2129 | vfp_sys_reg = asm_parse_vfp_status_regvar(tok); |
| 2268 | 2130 | next(); // skip vfp sys reg |
| 2269 | 2131 | if (arm_operand.type == OP_REG32 && arm_operand.reg == 15 && vfp_sys_reg != 1) { |
| 2270 | 2132 | tcc_error("'%s' only supports the variant 'vmrs apsr_nzcv, fpscr' here", get_tok_str(token, NULL)); |
| 2271 | − return; | |
| 2272 | 2133 | } |
| 2273 | 2134 | break; |
| 2274 | 2135 | case TOK_ASM_vmsreq: |
| 2275 | 2136 | opcode = 0xe; |
| 2276 | 2137 | vfp_sys_reg = asm_parse_vfp_status_regvar(tok); |
| 2277 | 2138 | next(); // skip vfp sys reg |
| 2278 | − if (tok != ',') | |
| 2279 | − expect("','"); | |
| 2280 | − else | |
| 2281 | − next(); // skip ',' | |
| 2139 | + skip(','); | |
| 2282 | 2140 | parse_operand(s1, &arm_operand); |
| 2283 | 2141 | if (arm_operand.type == OP_REG32 && arm_operand.reg == 15) { |
| 2284 | 2142 | tcc_error("'%s' does not support 'pc' as operand", get_tok_str(token, NULL)); |
| 2285 | − return; | |
| 2286 | 2143 | } |
| 2287 | 2144 | break; |
| 2288 | 2145 | default: |
| 2289 | 2146 | expect("floating point status register instruction"); |
| 2290 | − return; | |
| 2291 | 2147 | } |
| 2292 | 2148 | if (vfp_sys_reg == -1) { |
| 2293 | 2149 | expect("VFP system register"); |
| 2294 | − return; | |
| 2295 | 2150 | } |
| 2296 | 2151 | if (arm_operand.type != OP_REG32) { |
| 2297 | 2152 | expect("ARM register"); |
| 2298 | − return; | |
| 2299 | 2153 | } |
| 2300 | 2154 | asm_emit_coprocessor_opcode(condition_code_of_token(token), coprocessor, opcode, arm_operand.reg, vfp_sys_reg, 0x10, 0, 0); |
| 2301 | 2155 | } |
| @@ -2327,24 +2181,17 @@ static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token) · 25 unmodified lines | ||
| 2327 | 2181 | opcode |= ENCODE_RD(ops[0].reg); |
| 2328 | 2182 | else { |
| 2329 | 2183 | expect("(destination operand) register"); |
| 2330 | − return; | |
| 2331 | 2184 | } |
| 2332 | 2185 | if (tok != ',') |
| 2333 | 2186 | expect("at least two arguments"); |
| 2334 | 2187 | else |
| 2335 | 2188 | next(); // skip ',' |
| 2336 | − | |
| 2337 | − if (tok != '[') | |
| 2338 | − expect("'['"); | |
| 2339 | − else | |
| 2340 | − next(); // skip '[' | |
| 2341 | − | |
| 2189 | + skip('['); | |
| 2342 | 2190 | parse_operand(s1, &ops[1]); |
| 2343 | 2191 | if (ops[1].type == OP_REG32) |
| 2344 | 2192 | opcode |= ENCODE_RN(ops[1].reg); |
| 2345 | 2193 | else { |
| 2346 | 2194 | expect("(first source operand) register"); |
| 2347 | − return; | |
| 2348 | 2195 | } |
| 2349 | 2196 | if (tok == ']') { |
| 2350 | 2197 | next(); |
| @@ -2365,10 +2212,7 @@ static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token) · 14 unmodified lines | ||
| 2365 | 2212 | opcode |= 1 << 24; // add offset before transfer |
| 2366 | 2213 | } |
| 2367 | 2214 | if (!closed_bracket) { |
| 2368 | − if (tok != ']') | |
| 2369 | − expect("']'"); | |
| 2370 | − else | |
| 2371 | − next(); // skip ']' | |
| 2215 | + skip(']'); | |
| 2372 | 2216 | opcode |= 1 << 24; // add offset before transfer |
| 2373 | 2217 | if (tok == '!') { |
| 2374 | 2218 | exclam = 1; |
| @@ -2379,7 +2223,6 @@ static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token) · 4 unmodified lines | ||
| 2379 | 2223 | if (exclam) { |
| 2380 | 2224 | if ((opcode & (1 << 24)) == 0) { |
| 2381 | 2225 | tcc_error("result of '%s' would be unpredictable here", get_tok_str(token, NULL)); |
| 2382 | − return; | |
| 2383 | 2226 | } |
| 2384 | 2227 | opcode |= 1 << 21; // write offset back into register |
| 2385 | 2228 | } |
| @@ -2465,7 +2308,6 @@ static void asm_branch_opcode(TCCState *s1, int token) · 79 unmodified lines | ||
| 2465 | 2308 | esym = elfsym(e.sym); |
| 2466 | 2309 | if (!esym || esym->st_shndx != cur_text_section->sh_num) { |
| 2467 | 2310 | tcc_error("invalid branch target"); |
| 2468 | − return; | |
| 2469 | 2311 | } |
| 2470 | 2312 | jmp_disp = encbranchoffset(ind, e.v + esym->st_value, 1); |
| 2471 | 2313 | break; |
| @@ -2518,7 +2360,6 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 46 unmodified lines | ||
| 2518 | 2360 | return; |
| 2519 | 2361 | default: |
| 2520 | 2362 | expect("instruction"); |
| 2521 | − return; | |
| 2522 | 2363 | } |
| 2523 | 2364 | } |
| 2524 | 2365 | |
| @@ -2740,7 +2581,6 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 215 unmodified lines | ||
| 2740 | 2581 | ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier) |
| 2741 | 2582 | { |
| 2742 | 2583 | int r, reg, size, val; |
| 2743 | − char buf[64]; | |
| 2744 | 2584 | |
| 2745 | 2585 | r = sv->r; |
| 2746 | 2586 | 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 | ||
| 2767 | 2607 | val = sv->c.i; |
| 2768 | 2608 | if (modifier == 'n') |
| 2769 | 2609 | 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); | |
| 2772 | 2611 | no_offset:; |
| 2773 | 2612 | } 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); | |
| 2776 | 2614 | } else if (r & VT_LVAL) { |
| 2777 | 2615 | reg = r & VT_VALMASK; |
| 2778 | 2616 | if (reg >= VT_CONST) |
| 2779 | 2617 | tcc_internal_error(""); |
| 2780 | − snprintf(buf, sizeof(buf), "[%s]", | |
| 2618 | + cstr_printf(add_str, "[%s]", | |
| 2781 | 2619 | get_tok_str(TOK_ASM_r0 + reg, NULL)); |
| 2782 | − cstr_cat(add_str, buf, -1); | |
| 2783 | 2620 | } else { |
| 2784 | 2621 | /* register case */ |
| 2785 | 2622 | reg = r & VT_VALMASK; |
| @@ -2808,8 +2645,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier) · 22 unmodified lines | ||
| 2808 | 2645 | reg = TOK_ASM_r0 + reg; |
| 2809 | 2646 | break; |
| 2810 | 2647 | } |
| 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)); | |
| 2813 | 2649 | } |
| 2814 | 2650 | } |
| 2815 | 2651 | |
| @@ -2928,7 +2764,6 @@ static inline int constraint_priority(const char *str) · 112 unmodified lines | ||
| 2928 | 2764 | break; |
| 2929 | 2765 | default: |
| 2930 | 2766 | tcc_error("unknown constraint '%c'", c); |
| 2931 | − pr = 0; | |
| 2932 | 2767 | } |
| 2933 | 2768 | if (pr > priority) |
| 2934 | 2769 | priority = pr; |
| @@ -30,7 +30,7 @@ enum float_abi { · 29 unmodified lines | ||
| 30 | 30 | #ifdef NEED_RELOC_TYPE |
| 31 | 31 | /* Returns 1 for a code relocation, 0 for a data relocation. For unknown |
| 32 | 32 | relocations, returns -1. */ |
| 33 | −int code_reloc (int reloc_type) | |
| 33 | +ST_FUNC int code_reloc (int reloc_type) | |
| 34 | 34 | { |
| 35 | 35 | switch (reloc_type) { |
| 36 | 36 | case R_ARM_MOVT_ABS: |
| @@ -68,7 +68,7 @@ int code_reloc (int reloc_type) · 31 unmodified lines | ||
| 68 | 68 | /* Returns an enumerator to describe whether and when the relocation needs a |
| 69 | 69 | GOT and/or PLT entry to be created. See tcc.h for a description of the |
| 70 | 70 | different values. */ |
| 71 | −int gotplt_entry_type (int reloc_type) | |
| 71 | +ST_FUNC int gotplt_entry_type (int reloc_type) | |
| 72 | 72 | { |
| 73 | 73 | switch (reloc_type) { |
| 74 | 74 | case R_ARM_NONE: |
| @@ -179,7 +179,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 104 unmodified lines | ||
| 179 | 179 | #endif |
| 180 | 180 | #endif |
| 181 | 181 | |
| 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) | |
| 183 | 183 | { |
| 184 | 184 | ElfW(Sym) *sym; |
| 185 | 185 | int sym_index, esym_index; |
| @@ -24,7 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #ifdef NEED_RELOC_TYPE |
| 25 | 25 | /* Returns 1 for a code relocation, 0 for a data relocation. For unknown |
| 26 | 26 | relocations, returns -1. */ |
| 27 | −int code_reloc (int reloc_type) | |
| 27 | +ST_FUNC int code_reloc (int reloc_type) | |
| 28 | 28 | { |
| 29 | 29 | switch (reloc_type) { |
| 30 | 30 | case R_AARCH64_ABS32: |
| @@ -58,7 +58,7 @@ int code_reloc (int reloc_type) · 27 unmodified lines | ||
| 58 | 58 | /* Returns an enumerator to describe whether and when the relocation needs a |
| 59 | 59 | GOT and/or PLT entry to be created. See tcc.h for a description of the |
| 60 | 60 | different values. */ |
| 61 | −int gotplt_entry_type (int reloc_type) | |
| 61 | +ST_FUNC int gotplt_entry_type (int reloc_type) | |
| 62 | 62 | { |
| 63 | 63 | switch (reloc_type) { |
| 64 | 64 | case R_AARCH64_PREL32: |
| @@ -168,7 +168,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 103 unmodified lines | ||
| 168 | 168 | #endif |
| 169 | 169 | #endif |
| 170 | 170 | |
| 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) | |
| 172 | 172 | { |
| 173 | 173 | int sym_index = ELFW(R_SYM)(rel->r_info), esym_index; |
| 174 | 174 | #ifdef DEBUG_RELOC |
| @@ -24,7 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | /* Returns 1 for a code relocation, 0 for a data relocation. For unknown |
| 26 | 26 | relocations, returns -1. */ |
| 27 | −int code_reloc (int reloc_type) | |
| 27 | +ST_FUNC int code_reloc (int reloc_type) | |
| 28 | 28 | { |
| 29 | 29 | switch (reloc_type) { |
| 30 | 30 | case R_C60_32: |
| @@ -45,7 +45,7 @@ int code_reloc (int reloc_type) · 14 unmodified lines | ||
| 45 | 45 | /* Returns an enumerator to describe whether and when the relocation needs a |
| 46 | 46 | GOT and/or PLT entry to be created. See tcc.h for a description of the |
| 47 | 47 | different values. */ |
| 48 | −int gotplt_entry_type (int reloc_type) | |
| 48 | +ST_FUNC int gotplt_entry_type (int reloc_type) | |
| 49 | 49 | { |
| 50 | 50 | switch (reloc_type) { |
| 51 | 51 | case R_C60_32: |
| @@ -91,7 +91,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 39 unmodified lines | ||
| 91 | 91 | } |
| 92 | 92 | } |
| 93 | 93 | |
| 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) | |
| 95 | 95 | { |
| 96 | 96 | switch(type) { |
| 97 | 97 | case R_C60_32: |
| @@ -143,10 +143,12 @@ enum { · 142 unmodified lines | ||
| 143 | 143 | # define TREG_XAX TREG_RAX |
| 144 | 144 | # define TREG_XCX TREG_RCX |
| 145 | 145 | # define TREG_XDX TREG_RDX |
| 146 | +# define TOK_ASM_xax TOK_ASM_rax | |
| 146 | 147 | #else |
| 147 | 148 | # define TREG_XAX TREG_EAX |
| 148 | 149 | # define TREG_XCX TREG_ECX |
| 149 | 150 | # define TREG_XDX TREG_EDX |
| 151 | +# define TOK_ASM_xax TOK_ASM_eax | |
| 150 | 152 | #endif |
| 151 | 153 | |
| 152 | 154 | typedef struct ASMInstr { |
| @@ -1505,7 +1507,6 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 1352 unmodified lines | ||
| 1505 | 1507 | SValue *sv, int modifier) |
| 1506 | 1508 | { |
| 1507 | 1509 | int r, reg, size, val; |
| 1508 | − char buf[64]; | |
| 1509 | 1510 | |
| 1510 | 1511 | r = sv->r; |
| 1511 | 1512 | if ((r & VT_VALMASK) == VT_CONST) { |
| @@ -1532,32 +1533,19 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 20 unmodified lines | ||
| 1532 | 1533 | val = sv->c.i; |
| 1533 | 1534 | if (modifier == 'n') |
| 1534 | 1535 | 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); | |
| 1537 | 1537 | no_offset:; |
| 1538 | 1538 | #ifdef TCC_TARGET_X86_64 |
| 1539 | 1539 | if (r & VT_LVAL) |
| 1540 | 1540 | cstr_cat(add_str, "(%rip)", -1); |
| 1541 | 1541 | #endif |
| 1542 | 1542 | } 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)); | |
| 1549 | 1544 | } else if (r & VT_LVAL) { |
| 1550 | 1545 | reg = r & VT_VALMASK; |
| 1551 | 1546 | if (reg >= VT_CONST) |
| 1552 | 1547 | 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)); | |
| 1561 | 1549 | } else { |
| 1562 | 1550 | /* register case */ |
| 1563 | 1551 | reg = r & VT_VALMASK; |
| @@ -1617,8 +1605,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 53 unmodified lines | ||
| 1617 | 1605 | break; |
| 1618 | 1606 | #endif |
| 1619 | 1607 | } |
| 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)); | |
| 1622 | 1609 | } |
| 1623 | 1610 | } |
| 1624 | 1611 | |
| @@ -410,9 +410,7 @@ ST_FUNC void gfunc_call(int nb_args) · 409 unmodified lines | ||
| 410 | 410 | { |
| 411 | 411 | int size, align, r, args_size, i, func_call; |
| 412 | 412 | 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 | + | |
| 416 | 414 | #ifdef CONFIG_TCC_BCHECK |
| 417 | 415 | if (tcc_state->do_bounds_check) |
| 418 | 416 | gbound_args(nb_args); |
| @@ -420,12 +418,6 @@ ST_FUNC void gfunc_call(int nb_args) · 1 unmodified line | ||
| 420 | 418 | |
| 421 | 419 | args_size = 0; |
| 422 | 420 | 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 | |
| 429 | 421 | if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { |
| 430 | 422 | size = type_size(&vtop->type, &align); |
| 431 | 423 | /* align to stack align size */ |
| @@ -486,12 +478,15 @@ ST_FUNC void gfunc_call(int nb_args) · 54 unmodified lines | ||
| 486 | 478 | func_call = func_sym->f.func_call; |
| 487 | 479 | /* fast call case */ |
| 488 | 480 | if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) || |
| 489 | − func_call == FUNC_FASTCALLW) { | |
| 481 | + func_call == FUNC_FASTCALLW || func_call == FUNC_THISCALL) { | |
| 490 | 482 | int fastcall_nb_regs; |
| 491 | 483 | const uint8_t *fastcall_regs_ptr; |
| 492 | 484 | if (func_call == FUNC_FASTCALLW) { |
| 493 | 485 | fastcall_regs_ptr = fastcallw_regs; |
| 494 | 486 | fastcall_nb_regs = 2; |
| 487 | + } else if (func_call == FUNC_THISCALL) { | |
| 488 | + fastcall_regs_ptr = fastcallw_regs; | |
| 489 | + fastcall_nb_regs = 1; | |
| 495 | 490 | } else { |
| 496 | 491 | fastcall_regs_ptr = fastcall_regs; |
| 497 | 492 | fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1; |
| @@ -531,7 +526,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 33 unmodified lines | ||
| 531 | 526 | const uint8_t *fastcall_regs_ptr; |
| 532 | 527 | Sym *sym; |
| 533 | 528 | CType *type; |
| 534 | − int thiscall_nb_regs; | |
| 535 | 529 | |
| 536 | 530 | sym = func_type->ref; |
| 537 | 531 | func_call = sym->f.func_call; |
| @@ -545,15 +539,13 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 7 unmodified lines | ||
| 545 | 539 | } else if (func_call == FUNC_FASTCALLW) { |
| 546 | 540 | fastcall_nb_regs = 2; |
| 547 | 541 | fastcall_regs_ptr = fastcallw_regs; |
| 542 | + } else if (func_call == FUNC_THISCALL) { | |
| 543 | + fastcall_nb_regs = 1; | |
| 544 | + fastcall_regs_ptr = fastcallw_regs; | |
| 548 | 545 | } else { |
| 549 | 546 | fastcall_nb_regs = 0; |
| 550 | 547 | fastcall_regs_ptr = NULL; |
| 551 | 548 | } |
| 552 | − | |
| 553 | − if (func_call == FUNC_THISCALL) { | |
| 554 | − thiscall_nb_regs = 1; | |
| 555 | − } | |
| 556 | − | |
| 557 | 549 | param_index = 0; |
| 558 | 550 | |
| 559 | 551 | ind += FUNC_PROLOG_SIZE; |
| @@ -589,14 +581,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 29 unmodified lines | ||
| 589 | 581 | o(0x89); /* movl */ |
| 590 | 582 | gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc); |
| 591 | 583 | 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; | |
| 600 | 584 | } else { |
| 601 | 585 | param_addr = addr; |
| 602 | 586 | addr += size; |
| @@ -25,7 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #ifdef NEED_RELOC_TYPE |
| 26 | 26 | /* Returns 1 for a code relocation, 0 for a data relocation. For unknown |
| 27 | 27 | relocations, returns -1. */ |
| 28 | −int code_reloc (int reloc_type) | |
| 28 | +ST_FUNC int code_reloc (int reloc_type) | |
| 29 | 29 | { |
| 30 | 30 | switch (reloc_type) { |
| 31 | 31 | case R_386_RELATIVE: |
| @@ -55,7 +55,7 @@ int code_reloc (int reloc_type) · 23 unmodified lines | ||
| 55 | 55 | /* Returns an enumerator to describe whether and when the relocation needs a |
| 56 | 56 | GOT and/or PLT entry to be created. See tcc.h for a description of the |
| 57 | 57 | different values. */ |
| 58 | −int gotplt_entry_type (int reloc_type) | |
| 58 | +ST_FUNC int gotplt_entry_type (int reloc_type) | |
| 59 | 59 | { |
| 60 | 60 | switch (reloc_type) { |
| 61 | 61 | case R_386_RELATIVE: |
| @@ -171,7 +171,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 109 unmodified lines | ||
| 171 | 171 | #endif |
| 172 | 172 | #endif |
| 173 | 173 | |
| 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) | |
| 175 | 175 | { |
| 176 | 176 | int sym_index, esym_index; |
| 177 | 177 | |
| @@ -201,7 +201,8 @@ ST_FUNC char *tcc_load_text(int fd) · 200 unmodified lines | ||
| 201 | 201 | { |
| 202 | 202 | int len = lseek(fd, 0, SEEK_END); |
| 203 | 203 | char *buf = load_data(fd, 0, len + 1); |
| 204 | − buf[len] = 0; | |
| 204 | + if (buf) | |
| 205 | + buf[len] = 0; | |
| 205 | 206 | return buf; |
| 206 | 207 | } |
| 207 | 208 | |
| @@ -336,7 +337,8 @@ PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line) · 128 unmodified lines | ||
| 336 | 337 | { |
| 337 | 338 | int ofs; |
| 338 | 339 | mem_debug_header_t *header; |
| 339 | − | |
| 340 | + if (!size) | |
| 341 | + return NULL; | |
| 340 | 342 | header = tcc_malloc(sizeof(mem_debug_header_t) + size); |
| 341 | 343 | header->magic1 = MEM_DEBUG_MAGIC1; |
| 342 | 344 | 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 | ||
| 346 | 348 | ofs = strlen(file) - MEM_DEBUG_FILE_LEN; |
| 347 | 349 | strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN); |
| 348 | 350 | header->file_name[MEM_DEBUG_FILE_LEN] = 0; |
| 349 | − | |
| 350 | 351 | WAIT_SEM(&mem_sem); |
| 351 | 352 | header->next = mem_debug_chain; |
| 352 | 353 | header->prev = NULL; |
| @@ -357,7 +358,6 @@ PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line) · 4 unmodified lines | ||
| 357 | 358 | if (mem_cur_size > mem_max_size) |
| 358 | 359 | mem_max_size = mem_cur_size; |
| 359 | 360 | POST_SEM(&mem_sem); |
| 360 | − | |
| 361 | 361 | return MEM_USER_PTR(header); |
| 362 | 362 | } |
| 363 | 363 | |
| @@ -367,7 +367,6 @@ PUB_FUNC void tcc_free_debug(void *ptr) · 3 unmodified lines | ||
| 367 | 367 | if (!ptr) |
| 368 | 368 | return; |
| 369 | 369 | header = malloc_check(ptr, "tcc_free"); |
| 370 | − | |
| 371 | 370 | WAIT_SEM(&mem_sem); |
| 372 | 371 | mem_cur_size -= header->size; |
| 373 | 372 | 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 | ||
| 385 | 384 | { |
| 386 | 385 | void *ptr; |
| 387 | 386 | ptr = tcc_malloc_debug(size,file,line); |
| 388 | − memset(ptr, 0, size); | |
| 387 | + if (size) | |
| 388 | + memset(ptr, 0, size); | |
| 389 | 389 | return ptr; |
| 390 | 390 | } |
| 391 | 391 | |
| @@ -393,10 +393,14 @@ PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file · 1 unmodified line | ||
| 393 | 393 | { |
| 394 | 394 | mem_debug_header_t *header; |
| 395 | 395 | int mem_debug_chain_update = 0; |
| 396 | + | |
| 396 | 397 | if (!ptr) |
| 397 | 398 | return tcc_malloc_debug(size, file, line); |
| 399 | + if (!size) { | |
| 400 | + tcc_free_debug(ptr); | |
| 401 | + return NULL; | |
| 402 | + } | |
| 398 | 403 | header = malloc_check(ptr, "tcc_realloc"); |
| 399 | − | |
| 400 | 404 | WAIT_SEM(&mem_sem); |
| 401 | 405 | mem_cur_size -= header->size; |
| 402 | 406 | 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 | ||
| 413 | 417 | if (mem_cur_size > mem_max_size) |
| 414 | 418 | mem_max_size = mem_cur_size; |
| 415 | 419 | POST_SEM(&mem_sem); |
| 416 | − | |
| 417 | 420 | return MEM_USER_PTR(header); |
| 418 | 421 | } |
| 419 | 422 | |
| @@ -441,6 +444,7 @@ PUB_FUNC void tcc_memcheck(int d) · 21 unmodified lines | ||
| 441 | 444 | } |
| 442 | 445 | fflush(stderr); |
| 443 | 446 | mem_cur_size = 0; |
| 447 | + mem_max_size = 0; | |
| 444 | 448 | mem_debug_chain = NULL; |
| 445 | 449 | #if MEM_DEBUG-0 == 2 |
| 446 | 450 | exit(2); |
| @@ -1425,24 +1429,24 @@ static int tcc_set_linker(TCCState *s, const char *option) · 978 unmodified lines | ||
| 1425 | 1429 | s->pe_stack_size = strtoul(p, &end, 10); |
| 1426 | 1430 | } else if (link_option(option, "subsystem=", &p)) { |
| 1427 | 1431 | #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) |
| 1428 | − if (!strcmp(p, "native")) { | |
| 1432 | + if (strstart("native", &p)) { | |
| 1429 | 1433 | s->pe_subsystem = 1; |
| 1430 | − } else if (!strcmp(p, "console")) { | |
| 1434 | + } else if (strstart("console", &p)) { | |
| 1431 | 1435 | s->pe_subsystem = 3; |
| 1432 | − } else if (!strcmp(p, "gui") || !strcmp(p, "windows")) { | |
| 1436 | + } else if (strstart("gui", &p) || strstart("windows", &p)) { | |
| 1433 | 1437 | s->pe_subsystem = 2; |
| 1434 | − } else if (!strcmp(p, "posix")) { | |
| 1438 | + } else if (strstart("posix", &p)) { | |
| 1435 | 1439 | s->pe_subsystem = 7; |
| 1436 | − } else if (!strcmp(p, "efiapp")) { | |
| 1440 | + } else if (strstart("efiapp", &p)) { | |
| 1437 | 1441 | s->pe_subsystem = 10; |
| 1438 | − } else if (!strcmp(p, "efiboot")) { | |
| 1442 | + } else if (strstart("efiboot", &p)) { | |
| 1439 | 1443 | s->pe_subsystem = 11; |
| 1440 | − } else if (!strcmp(p, "efiruntime")) { | |
| 1444 | + } else if (strstart("efiruntime", &p)) { | |
| 1441 | 1445 | s->pe_subsystem = 12; |
| 1442 | − } else if (!strcmp(p, "efirom")) { | |
| 1446 | + } else if (strstart("efirom", &p)) { | |
| 1443 | 1447 | s->pe_subsystem = 13; |
| 1444 | 1448 | #elif defined(TCC_TARGET_ARM) |
| 1445 | − if (!strcmp(p, "wince")) { | |
| 1449 | + if (strstart("wince", &p)) { | |
| 1446 | 1450 | s->pe_subsystem = 9; |
| 1447 | 1451 | #endif |
| 1448 | 1452 | } else |
| @@ -2211,3 +2215,9 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time) · 762 unmodified lines | ||
| 2211 | 2215 | fprintf(stderr, " %d max (bytes)\n", mem_max_size); |
| 2212 | 2216 | #endif |
| 2213 | 2217 | } |
| 2218 | + | |
| 2219 | +#if ONE_SOURCE | |
| 2220 | +# undef malloc | |
| 2221 | +# undef realloc | |
| 2222 | +# undef free | |
| 2223 | +#endif | |
| @@ -48,6 +48,10 @@ typedef struct Operand { · 47 unmodified lines | ||
| 48 | 48 | }; |
| 49 | 49 | } Operand; |
| 50 | 50 | |
| 51 | +static const Operand zero = { OP_REG, { 0 }}; | |
| 52 | +static const Operand ra = { OP_REG, { 1 }}; | |
| 53 | +static const Operand zimm = { OP_IM12S }; | |
| 54 | + | |
| 51 | 55 | static void asm_binary_opcode(TCCState* s1, int token); |
| 52 | 56 | ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str); |
| 53 | 57 | 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 | ||
| 128 | 132 | |
| 129 | 133 | static void asm_nullary_opcode(TCCState *s1, int token) |
| 130 | 134 | { |
| 131 | − static const Operand nil = {.type = OP_REG}; | |
| 132 | − static const Operand zimm = {.type = OP_IM12S}; | |
| 133 | − | |
| 134 | 135 | switch (token) { |
| 135 | 136 | // Sync instructions |
| 136 | 137 | |
| @@ -150,7 +151,7 @@ static void asm_nullary_opcode(TCCState *s1, int token) · 13 unmodified lines | ||
| 150 | 151 | // Other |
| 151 | 152 | |
| 152 | 153 | 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); | |
| 154 | 155 | return; |
| 155 | 156 | |
| 156 | 157 | case TOK_ASM_wfi: |
| @@ -165,10 +166,10 @@ static void asm_nullary_opcode(TCCState *s1, int token) · 8 unmodified lines | ||
| 165 | 166 | |
| 166 | 167 | /* C extension */ |
| 167 | 168 | 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); | |
| 169 | 170 | return; |
| 170 | 171 | case TOK_ASM_c_nop: |
| 171 | − asm_emit_ci(token, 1, &nil, &zimm); | |
| 172 | + asm_emit_ci(token, 1, &zero, &zimm); | |
| 172 | 173 | return; |
| 173 | 174 | |
| 174 | 175 | default: |
| @@ -266,33 +267,24 @@ static void parse_jump_offset_operand(TCCState *s1, Operand *op){ · 91 unmodified lines | ||
| 266 | 267 | static void parse_operands(TCCState *s1, Operand* ops, int count){ |
| 267 | 268 | int i; |
| 268 | 269 | 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(','); | |
| 275 | 272 | parse_operand(s1, &ops[i]); |
| 276 | 273 | } |
| 277 | 274 | } |
| 278 | 275 | |
| 279 | 276 | /* parse `X, imm(Y)` to {X, Y, imm} operands */ |
| 280 | 277 | static void parse_mem_access_operands(TCCState *s1, Operand* ops){ |
| 281 | − static const Operand zimm = {.type = OP_IM12S}; | |
| 282 | 278 | |
| 283 | 279 | Operand op; |
| 284 | 280 | |
| 285 | 281 | parse_operand(s1, &ops[0]); |
| 286 | − if ( tok == ',') | |
| 287 | − next(); | |
| 288 | − else | |
| 289 | − expect("','"); | |
| 290 | − | |
| 282 | + skip(','); | |
| 291 | 283 | if ( tok == '(') { |
| 292 | 284 | /* `X, (Y)` case*/ |
| 293 | 285 | next(); |
| 294 | 286 | parse_operand(s1, &ops[1]); |
| 295 | − if ( tok == ')') next(); else expect("')'"); | |
| 287 | + skip(')'); | |
| 296 | 288 | ops[2] = zimm; |
| 297 | 289 | } else { |
| 298 | 290 | parse_operand(s1, &ops[2]); |
| @@ -300,7 +292,7 @@ static void parse_mem_access_operands(TCCState *s1, Operand* ops){ · 1 unmodified line | ||
| 300 | 292 | /* `X, imm(Y)` case*/ |
| 301 | 293 | next(); |
| 302 | 294 | parse_operand(s1, &ops[1]); |
| 303 | − if ( tok == ')') next(); else expect("')'"); | |
| 295 | + skip(')'); | |
| 304 | 296 | } else { |
| 305 | 297 | /* `X, Y` case*/ |
| 306 | 298 | /* 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 | ||
| 314 | 306 | |
| 315 | 307 | /* This is special: First operand is optional */ |
| 316 | 308 | 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}; | |
| 319 | 309 | Operand ops[2]; |
| 320 | 310 | |
| 321 | 311 | if (token == TOK_ASM_j ){ |
| @@ -333,8 +323,6 @@ static void asm_jal_opcode(TCCState *s1, int token){ · 11 unmodified lines | ||
| 333 | 323 | |
| 334 | 324 | /* This is special: It can be a pseudointruction or a instruction */ |
| 335 | 325 | 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}; | |
| 338 | 326 | Operand ops[3]; |
| 339 | 327 | Operand op; |
| 340 | 328 | |
| @@ -355,7 +343,7 @@ static void asm_jalr_opcode(TCCState *s1, int token){ · 14 unmodified lines | ||
| 355 | 343 | /* `X, (Y)` case*/ |
| 356 | 344 | next(); |
| 357 | 345 | parse_operand(s1, &ops[1]); |
| 358 | − if ( tok == ')') next(); else expect("')'"); | |
| 346 | + skip(')'); | |
| 359 | 347 | ops[2] = zimm; |
| 360 | 348 | } else { |
| 361 | 349 | parse_operand(s1, &ops[2]); |
| @@ -363,7 +351,7 @@ static void asm_jalr_opcode(TCCState *s1, int token){ · 1 unmodified line | ||
| 363 | 351 | /* `X, imm(Y)` case*/ |
| 364 | 352 | next(); |
| 365 | 353 | parse_operand(s1, &ops[1]); |
| 366 | − if ( tok == ')') next(); else expect("')'"); | |
| 354 | + skip(')'); | |
| 367 | 355 | } else { |
| 368 | 356 | /* `X, Y` case*/ |
| 369 | 357 | /* 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 | ||
| 382 | 370 | { |
| 383 | 371 | uint32_t opcode = (0x1C << 2) | 3 | (2 << 12); |
| 384 | 372 | Operand op; |
| 385 | − static const Operand zero = {.type = OP_REG}; | |
| 386 | − static const Operand zimm = {.type = OP_IM12S}; | |
| 387 | 373 | |
| 388 | 374 | parse_operands(s1, &op, 1); |
| 389 | 375 | /* 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 | ||
| 451 | 437 | { |
| 452 | 438 | if (rd->type != OP_REG) { |
| 453 | 439 | tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL)); |
| 454 | − return; | |
| 455 | 440 | } |
| 456 | 441 | if (rs2->type != OP_IM12S && rs2->type != OP_IM32) { |
| 457 | 442 | tcc_error("'%s': Expected second source operand that is an immediate value", get_tok_str(token, NULL)); |
| 458 | − return; | |
| 459 | 443 | } else if (rs2->e.v >= 0x100000) { |
| 460 | 444 | tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 0xfffff", get_tok_str(token, NULL)); |
| 461 | − return; | |
| 462 | 445 | } |
| 463 | 446 | /* U-type instruction: |
| 464 | 447 | 31...12 imm[31:12] |
| @@ -486,7 +469,7 @@ static void asm_fence_opcode(TCCState *s1, int token){ · 21 unmodified lines | ||
| 486 | 469 | if ( pred > 0xF || pred < 0) { |
| 487 | 470 | tcc_error("'%s': Expected first operand that is a valid predecessor operand", get_tok_str(token, NULL)); |
| 488 | 471 | } |
| 489 | − if ( tok == ',') next(); else expect("','"); | |
| 472 | + skip(','); | |
| 490 | 473 | succ = parse_fence_operand(); |
| 491 | 474 | if ( succ > 0xF || succ < 0) { |
| 492 | 475 | 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 | ||
| 497 | 480 | |
| 498 | 481 | static void asm_binary_opcode(TCCState* s1, int token) |
| 499 | 482 | { |
| 500 | − static const Operand zero = {.type = OP_REG, .reg = 0}; | |
| 501 | − Operand imm = {.type = OP_IM12S, .e = {.v = 0}}; | |
| 483 | + Operand imm = { OP_IM12S }; | |
| 502 | 484 | Operand ops[2]; |
| 503 | 485 | int32_t lo; |
| 504 | 486 | 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 | ||
| 710 | 692 | { |
| 711 | 693 | if (rd->type != OP_REG) { |
| 712 | 694 | tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL)); |
| 713 | − return; | |
| 714 | 695 | } |
| 715 | 696 | if (rs1->type != OP_REG) { |
| 716 | 697 | tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL)); |
| 717 | − return; | |
| 718 | 698 | } |
| 719 | 699 | if (rs2->type != OP_REG) { |
| 720 | 700 | tcc_error("'%s': Expected second source operand that is a register or immediate", get_tok_str(token, NULL)); |
| 721 | − return; | |
| 722 | 701 | } |
| 723 | 702 | /* R-type instruction: |
| 724 | 703 | 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 | ||
| 735 | 714 | { |
| 736 | 715 | if (rd->type != OP_REG) { |
| 737 | 716 | tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL)); |
| 738 | − return; | |
| 739 | 717 | } |
| 740 | 718 | if (rs1->type != OP_REG) { |
| 741 | 719 | tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL)); |
| 742 | − return; | |
| 743 | 720 | } |
| 744 | 721 | if (rs2->type != OP_IM12S) { |
| 745 | 722 | tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 8191", get_tok_str(token, NULL)); |
| 746 | − return; | |
| 747 | 723 | } |
| 748 | 724 | /* I-type instruction: |
| 749 | 725 | 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 | ||
| 761 | 737 | |
| 762 | 738 | if (rd->type != OP_REG) { |
| 763 | 739 | tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL)); |
| 764 | − return; | |
| 765 | 740 | } |
| 766 | 741 | if (rs2->type != OP_IM12S && rs2->type != OP_IM32) { |
| 767 | 742 | tcc_error("'%s': Expected second source operand that is an immediate value", get_tok_str(token, NULL)); |
| 768 | − return; | |
| 769 | 743 | } |
| 770 | 744 | |
| 771 | 745 | 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 | ||
| 773 | 747 | /* even offsets in a +- 1 MiB range */ |
| 774 | 748 | if ((int)imm > (1 << 20) -1 || (int)imm <= -1 * ((1 << 20) -1)) { |
| 775 | 749 | tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 0x1fffff", get_tok_str(token, NULL)); |
| 776 | − return; | |
| 777 | 750 | } |
| 778 | 751 | |
| 779 | 752 | if (imm & 1) { |
| 780 | 753 | tcc_error("'%s': Expected second source operand that is an even immediate value", get_tok_str(token, NULL)); |
| 781 | − return; | |
| 782 | 754 | } |
| 783 | 755 | /* J-type instruction: |
| 784 | 756 | 31 imm[20] |
| @@ -851,11 +823,11 @@ static void asm_mem_access_opcode(TCCState *s1, int token) · 66 unmodified lines | ||
| 851 | 823 | } |
| 852 | 824 | } |
| 853 | 825 | |
| 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 | +{ | |
| 855 | 828 | Operand ops[3]; |
| 856 | − Operand zero = {.type = OP_REG}; | |
| 857 | 829 | parse_operands(s1, &ops[0], argc-1); |
| 858 | − if ( tok == ',') next(); else { expect(","); } | |
| 830 | + skip(','); | |
| 859 | 831 | parse_branch_offset_operand(s1, &ops[argc-1]); |
| 860 | 832 | |
| 861 | 833 | switch(token){ |
| @@ -1118,22 +1090,21 @@ static void asm_ternary_opcode(TCCState *s1, int token) · 256 unmodified lines | ||
| 1118 | 1090 | |
| 1119 | 1091 | static void asm_atomic_opcode(TCCState *s1, int token) |
| 1120 | 1092 | { |
| 1121 | − static const Operand zero = {.type = OP_REG}; | |
| 1122 | 1093 | Operand ops[3]; |
| 1123 | 1094 | |
| 1124 | 1095 | parse_operand(s1, &ops[0]); |
| 1125 | − if ( tok == ',') next(); else expect("','"); | |
| 1096 | + skip(','); | |
| 1126 | 1097 | |
| 1127 | 1098 | if ( token <= TOK_ASM_lr_d_aqrl && token >= TOK_ASM_lr_w ) { |
| 1128 | 1099 | ops[1] = zero; |
| 1129 | 1100 | } else { |
| 1130 | 1101 | parse_operand(s1, &ops[1]); |
| 1131 | − if ( tok == ',') next(); else expect("','"); | |
| 1102 | + skip(','); | |
| 1132 | 1103 | } |
| 1133 | 1104 | |
| 1134 | − if ( tok == '(') next(); else expect("'('"); | |
| 1105 | + skip('('); | |
| 1135 | 1106 | parse_operand(s1, &ops[2]); |
| 1136 | − if ( tok == ')') next(); else expect("')'"); | |
| 1107 | + skip(')'); | |
| 1137 | 1108 | |
| 1138 | 1109 | switch(token){ |
| 1139 | 1110 | 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 | ||
| 1217 | 1188 | { |
| 1218 | 1189 | if (rs1->type != OP_REG) { |
| 1219 | 1190 | tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL)); |
| 1220 | − return; | |
| 1221 | 1191 | } |
| 1222 | 1192 | if (rs2->type != OP_REG) { |
| 1223 | 1193 | tcc_error("'%s': Expected second source operand that is a register", get_tok_str(token, NULL)); |
| 1224 | − return; | |
| 1225 | 1194 | } |
| 1226 | 1195 | if (imm->type != OP_IM12S) { |
| 1227 | 1196 | tcc_error("'%s': Expected third operand that is an immediate value between 0 and 8191", get_tok_str(token, NULL)); |
| 1228 | − return; | |
| 1229 | 1197 | } |
| 1230 | 1198 | { |
| 1231 | 1199 | 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 | ||
| 1247 | 1215 | |
| 1248 | 1216 | if (rs1->type != OP_REG) { |
| 1249 | 1217 | tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL)); |
| 1250 | − return; | |
| 1251 | 1218 | } |
| 1252 | 1219 | if (rs2->type != OP_REG) { |
| 1253 | 1220 | tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL)); |
| 1254 | − return; | |
| 1255 | 1221 | } |
| 1256 | 1222 | if (imm->type != OP_IM12S) { |
| 1257 | 1223 | tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 8191", get_tok_str(token, NULL)); |
| 1258 | − return; | |
| 1259 | 1224 | } |
| 1260 | 1225 | |
| 1261 | 1226 | offset = imm->e.v; |
| @@ -1541,7 +1506,6 @@ static int asm_parse_csrvar(int t) · 279 unmodified lines | ||
| 1541 | 1506 | ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier) |
| 1542 | 1507 | { |
| 1543 | 1508 | int r, reg, val; |
| 1544 | − char buf[64]; | |
| 1545 | 1509 | |
| 1546 | 1510 | r = sv->r; |
| 1547 | 1511 | 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 | ||
| 1572 | 1536 | if (modifier == 'z' && sv->c.i == 0) { |
| 1573 | 1537 | cstr_cat(add_str, "zero", -1); |
| 1574 | 1538 | } 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); | |
| 1577 | 1540 | } |
| 1578 | 1541 | no_offset:; |
| 1579 | 1542 | } 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); | |
| 1582 | 1544 | } else if (r & VT_LVAL) { |
| 1583 | 1545 | reg = r & VT_VALMASK; |
| 1584 | 1546 | if (reg >= VT_CONST) |
| @@ -1591,8 +1553,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier) · 6 unmodified lines | ||
| 1591 | 1553 | /* general purpose register */ |
| 1592 | 1554 | reg = TOK_ASM_x0 + reg; |
| 1593 | 1555 | } |
| 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); | |
| 1596 | 1557 | } else { |
| 1597 | 1558 | /* register case */ |
| 1598 | 1559 | reg = r & VT_VALMASK; |
| @@ -1606,8 +1567,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier) · 7 unmodified lines | ||
| 1606 | 1567 | /* general purpose register */ |
| 1607 | 1568 | reg = TOK_ASM_x0 + reg; |
| 1608 | 1569 | } |
| 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); | |
| 1611 | 1571 | } |
| 1612 | 1572 | } |
| 1613 | 1573 | |
| @@ -1775,12 +1735,9 @@ static inline int constraint_priority(const char *str) · 161 unmodified lines | ||
| 1775 | 1735 | pr = 4; |
| 1776 | 1736 | break; |
| 1777 | 1737 | case 'v': |
| 1778 | − tcc_error("unimp: vector constraints '%d'", c); | |
| 1779 | − pr = 0; | |
| 1780 | − break; | |
| 1738 | + tcc_error("unimp: constraint '%c'", c); | |
| 1781 | 1739 | default: |
| 1782 | 1740 | tcc_error("unknown constraint '%d'", c); |
| 1783 | − pr = 0; | |
| 1784 | 1741 | } |
| 1785 | 1742 | if (pr > priority) |
| 1786 | 1743 | priority = pr; |
| @@ -2093,12 +2050,10 @@ static void asm_emit_ca(int token, uint16_t opcode, const Operand *rd, const Ope · 306 unmodified lines | ||
| 2093 | 2050 | |
| 2094 | 2051 | if (rd->type != OP_REG) { |
| 2095 | 2052 | tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL)); |
| 2096 | − return; | |
| 2097 | 2053 | } |
| 2098 | 2054 | |
| 2099 | 2055 | if (rs2->type != OP_REG) { |
| 2100 | 2056 | tcc_error("'%s': Expected source operand that is a register", get_tok_str(token, NULL)); |
| 2101 | − return; | |
| 2102 | 2057 | } |
| 2103 | 2058 | |
| 2104 | 2059 | /* 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 | ||
| 2108 | 2063 | /* only registers {x,f}8 to {x,f}15 are valid (3-bit) */ |
| 2109 | 2064 | if (dst > 7) { |
| 2110 | 2065 | tcc_error("'%s': Expected destination operand that is a valid C-extension register", get_tok_str(token, NULL)); |
| 2111 | − return; | |
| 2112 | 2066 | } |
| 2113 | 2067 | |
| 2114 | 2068 | if (src > 7) { |
| 2115 | 2069 | tcc_error("'%s': Expected source operand that is a valid C-extension register", get_tok_str(token, NULL)); |
| 2116 | − return; | |
| 2117 | 2070 | } |
| 2118 | 2071 | |
| 2119 | 2072 | /* 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 | ||
| 2133 | 2086 | |
| 2134 | 2087 | if (rs1->type != OP_REG) { |
| 2135 | 2088 | tcc_error("'%s': Expected source operand that is a register", get_tok_str(token, NULL)); |
| 2136 | − return; | |
| 2137 | 2089 | } |
| 2138 | 2090 | |
| 2139 | 2091 | if (imm->type != OP_IM12S && imm->type != OP_IM32) { |
| 2140 | 2092 | tcc_error("'%s': Expected source operand that is an immediate value", get_tok_str(token, NULL)); |
| 2141 | − return; | |
| 2142 | 2093 | } |
| 2143 | 2094 | |
| 2144 | 2095 | offset = imm->e.v; |
| 2145 | 2096 | |
| 2146 | 2097 | if (offset & 1) { |
| 2147 | 2098 | tcc_error("'%s': Expected source operand that is an even immediate value", get_tok_str(token, NULL)); |
| 2148 | − return; | |
| 2149 | 2099 | } |
| 2150 | 2100 | |
| 2151 | 2101 | src = rs1->reg - 8; |
| 2152 | 2102 | |
| 2153 | 2103 | if (src > 7) { |
| 2154 | 2104 | tcc_error("'%s': Expected source operand that is a valid C-extension register", get_tok_str(token, NULL)); |
| 2155 | − return; | |
| 2156 | 2105 | } |
| 2157 | 2106 | |
| 2158 | 2107 | /* 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 | ||
| 2187 | 2136 | |
| 2188 | 2137 | if (rd->type != OP_REG) { |
| 2189 | 2138 | tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL)); |
| 2190 | − return; | |
| 2191 | 2139 | } |
| 2192 | 2140 | |
| 2193 | 2141 | if (imm->type != OP_IM12S && imm->type != OP_IM32) { |
| 2194 | 2142 | tcc_error("'%s': Expected source operand that is an immediate value", get_tok_str(token, NULL)); |
| 2195 | − return; | |
| 2196 | 2143 | } |
| 2197 | 2144 | |
| 2198 | 2145 | 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 | ||
| 2241 | 2188 | |
| 2242 | 2189 | if (rd->type != OP_REG) { |
| 2243 | 2190 | tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL)); |
| 2244 | − return; | |
| 2245 | 2191 | } |
| 2246 | 2192 | |
| 2247 | 2193 | if (imm->type != OP_IM12S && imm->type != OP_IM32) { |
| 2248 | 2194 | tcc_error("'%s': Expected source operand that is an immediate value", get_tok_str(token, NULL)); |
| 2249 | − return; | |
| 2250 | 2195 | } |
| 2251 | 2196 | |
| 2252 | 2197 | dst = rd->reg - 8; |
| 2253 | 2198 | |
| 2254 | 2199 | if (dst > 7) { |
| 2255 | 2200 | tcc_error("'%s': Expected destination operand that is a valid C-extension register", get_tok_str(token, NULL)); |
| 2256 | − return; | |
| 2257 | 2201 | } |
| 2258 | 2202 | |
| 2259 | 2203 | nzuimm = imm->e.v; |
| 2260 | 2204 | |
| 2261 | 2205 | if (nzuimm > 0x3fc) { |
| 2262 | 2206 | tcc_error("'%s': Expected source operand that is an immediate value between 0 and 0x3ff", get_tok_str(token, NULL)); |
| 2263 | − return; | |
| 2264 | 2207 | } |
| 2265 | 2208 | |
| 2266 | 2209 | if (nzuimm & 3) { |
| 2267 | 2210 | tcc_error("'%s': Expected source operand that is a non-zero immediate value divisible by 4", get_tok_str(token, NULL)); |
| 2268 | − return; | |
| 2269 | 2211 | } |
| 2270 | 2212 | |
| 2271 | 2213 | /* CIW-type instruction: |
| @@ -2285,14 +2227,12 @@ static void asm_emit_cj(int token, uint16_t opcode, const Operand *imm) · 13 unmodified lines | ||
| 2285 | 2227 | /* +-2 KiB range */ |
| 2286 | 2228 | if (imm->type != OP_IM12S) { |
| 2287 | 2229 | tcc_error("'%s': Expected source operand that is a 12-bit immediate value", get_tok_str(token, NULL)); |
| 2288 | − return; | |
| 2289 | 2230 | } |
| 2290 | 2231 | |
| 2291 | 2232 | offset = imm->e.v; |
| 2292 | 2233 | |
| 2293 | 2234 | if (offset & 1) { |
| 2294 | 2235 | tcc_error("'%s': Expected source operand that is an even immediate value", get_tok_str(token, NULL)); |
| 2295 | − return; | |
| 2296 | 2236 | } |
| 2297 | 2237 | |
| 2298 | 2238 | /* 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 | ||
| 2311 | 2251 | |
| 2312 | 2252 | if (rd->type != OP_REG) { |
| 2313 | 2253 | tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL)); |
| 2314 | − return; | |
| 2315 | 2254 | } |
| 2316 | 2255 | |
| 2317 | 2256 | if (rs1->type != OP_REG) { |
| 2318 | 2257 | tcc_error("'%s': Expected source operand that is a register", get_tok_str(token, NULL)); |
| 2319 | − return; | |
| 2320 | 2258 | } |
| 2321 | 2259 | |
| 2322 | 2260 | if (imm->type != OP_IM12S && imm->type != OP_IM32) { |
| 2323 | 2261 | tcc_error("'%s': Expected source operand that is an immediate value", get_tok_str(token, NULL)); |
| 2324 | − return; | |
| 2325 | 2262 | } |
| 2326 | 2263 | |
| 2327 | 2264 | 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 | ||
| 2329 | 2266 | |
| 2330 | 2267 | if (dst > 7) { |
| 2331 | 2268 | tcc_error("'%s': Expected destination operand that is a valid C-extension register", get_tok_str(token, NULL)); |
| 2332 | − return; | |
| 2333 | 2269 | } |
| 2334 | 2270 | |
| 2335 | 2271 | if (src > 7) { |
| 2336 | 2272 | tcc_error("'%s': Expected source operand that is a valid C-extension register", get_tok_str(token, NULL)); |
| 2337 | − return; | |
| 2338 | 2273 | } |
| 2339 | 2274 | |
| 2340 | 2275 | offset = imm->e.v; |
| 2341 | 2276 | |
| 2342 | 2277 | if (offset > 0xff) { |
| 2343 | 2278 | tcc_error("'%s': Expected source operand that is an immediate value between 0 and 0xff", get_tok_str(token, NULL)); |
| 2344 | − return; | |
| 2345 | 2279 | } |
| 2346 | 2280 | |
| 2347 | 2281 | if (offset & 3) { |
| 2348 | 2282 | tcc_error("'%s': Expected source operand that is an immediate value divisible by 4", get_tok_str(token, NULL)); |
| 2349 | − return; | |
| 2350 | 2283 | } |
| 2351 | 2284 | |
| 2352 | 2285 | /* 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 | ||
| 2378 | 2311 | { |
| 2379 | 2312 | if (rd->type != OP_REG) { |
| 2380 | 2313 | tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL)); |
| 2381 | − return; | |
| 2382 | 2314 | } |
| 2383 | 2315 | |
| 2384 | 2316 | if (rs2->type != OP_REG) { |
| 2385 | 2317 | tcc_error("'%s': Expected source operand that is a register", get_tok_str(token, NULL)); |
| 2386 | − return; | |
| 2387 | 2318 | } |
| 2388 | 2319 | |
| 2389 | 2320 | /* 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 | ||
| 2403 | 2334 | |
| 2404 | 2335 | if (rs2->type != OP_REG) { |
| 2405 | 2336 | tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL)); |
| 2406 | − return; | |
| 2407 | 2337 | } |
| 2408 | 2338 | |
| 2409 | 2339 | if (rs1->type != OP_REG) { |
| 2410 | 2340 | tcc_error("'%s': Expected source operand that is a register", get_tok_str(token, NULL)); |
| 2411 | − return; | |
| 2412 | 2341 | } |
| 2413 | 2342 | |
| 2414 | 2343 | if (imm->type != OP_IM12S && imm->type != OP_IM32) { |
| 2415 | 2344 | tcc_error("'%s': Expected source operand that is an immediate value", get_tok_str(token, NULL)); |
| 2416 | − return; | |
| 2417 | 2345 | } |
| 2418 | 2346 | |
| 2419 | 2347 | 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 | ||
| 2421 | 2349 | |
| 2422 | 2350 | if (base > 7) { |
| 2423 | 2351 | tcc_error("'%s': Expected destination operand that is a valid C-extension register", get_tok_str(token, NULL)); |
| 2424 | − return; | |
| 2425 | 2352 | } |
| 2426 | 2353 | |
| 2427 | 2354 | if (src > 7) { |
| 2428 | 2355 | tcc_error("'%s': Expected source operand that is a valid C-extension register", get_tok_str(token, NULL)); |
| 2429 | − return; | |
| 2430 | 2356 | } |
| 2431 | 2357 | |
| 2432 | 2358 | offset = imm->e.v; |
| 2433 | 2359 | |
| 2434 | 2360 | if (offset > 0xff) { |
| 2435 | 2361 | tcc_error("'%s': Expected source operand that is an immediate value between 0 and 0xff", get_tok_str(token, NULL)); |
| 2436 | − return; | |
| 2437 | 2362 | } |
| 2438 | 2363 | |
| 2439 | 2364 | if (offset & 3) { |
| 2440 | 2365 | tcc_error("'%s': Expected source operand that is an immediate value divisible by 4", get_tok_str(token, NULL)); |
| 2441 | − return; | |
| 2442 | 2366 | } |
| 2443 | 2367 | |
| 2444 | 2368 | /* 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 | ||
| 2471 | 2395 | |
| 2472 | 2396 | if (rs2->type != OP_REG) { |
| 2473 | 2397 | tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL)); |
| 2474 | − return; | |
| 2475 | 2398 | } |
| 2476 | 2399 | |
| 2477 | 2400 | if (imm->type != OP_IM12S && imm->type != OP_IM32) { |
| 2478 | 2401 | tcc_error("'%s': Expected source operand that is an immediate value", get_tok_str(token, NULL)); |
| 2479 | − return; | |
| 2480 | 2402 | } |
| 2481 | 2403 | |
| 2482 | 2404 | offset = imm->e.v; |
| 2483 | 2405 | |
| 2484 | 2406 | if (offset > 0xff) { |
| 2485 | 2407 | tcc_error("'%s': Expected source operand that is an immediate value between 0 and 0xff", get_tok_str(token, NULL)); |
| 2486 | − return; | |
| 2487 | 2408 | } |
| 2488 | 2409 | |
| 2489 | 2410 | if (offset & 3) { |
| 2490 | 2411 | tcc_error("'%s': Expected source operand that is an immediate value divisible by 4", get_tok_str(token, NULL)); |
| 2491 | − return; | |
| 2492 | 2412 | } |
| 2493 | 2413 | |
| 2494 | 2414 | /* CSS-type instruction: |
| @@ -24,7 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | /* Returns 1 for a code relocation, 0 for a data relocation. For unknown |
| 26 | 26 | relocations, returns -1. */ |
| 27 | −int code_reloc (int reloc_type) | |
| 27 | +ST_FUNC int code_reloc (int reloc_type) | |
| 28 | 28 | { |
| 29 | 29 | switch (reloc_type) { |
| 30 | 30 | |
| @@ -62,7 +62,7 @@ int code_reloc (int reloc_type) · 31 unmodified lines | ||
| 62 | 62 | /* Returns an enumerator to describe whether and when the relocation needs a |
| 63 | 63 | GOT and/or PLT entry to be created. See tcc.h for a description of the |
| 64 | 64 | different values. */ |
| 65 | −int gotplt_entry_type (int reloc_type) | |
| 65 | +ST_FUNC int gotplt_entry_type (int reloc_type) | |
| 66 | 66 | { |
| 67 | 67 | switch (reloc_type) { |
| 68 | 68 | case R_RISCV_ALIGN: |
| @@ -169,7 +169,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 100 unmodified lines | ||
| 169 | 169 | } |
| 170 | 170 | } |
| 171 | 171 | |
| 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, | |
| 173 | 173 | addr_t addr, addr_t val) |
| 174 | 174 | { |
| 175 | 175 | uint64_t off64; |
| @@ -89,7 +89,6 @@ extern long double strtold (const char *__nptr, char **__endptr); · 88 unmodified lines | ||
| 89 | 89 | # ifndef va_copy |
| 90 | 90 | # define va_copy(a,b) a = b |
| 91 | 91 | # endif |
| 92 | −# undef CONFIG_TCC_STATIC | |
| 93 | 92 | #endif |
| 94 | 93 | |
| 95 | 94 | #ifndef O_BINARY |
| @@ -487,7 +486,7 @@ typedef int nwchar_t; · 391 unmodified lines | ||
| 487 | 486 | typedef struct CString { |
| 488 | 487 | int size; /* size in bytes */ |
| 489 | 488 | int size_allocated; |
| 490 | − void *data; /* either 'char *' or 'nwchar_t *' */ | |
| 489 | + char *data; /* nwchar_t* in cases */ | |
| 491 | 490 | } CString; |
| 492 | 491 | |
| 493 | 492 | /* type definition */ |
| @@ -1157,7 +1156,7 @@ struct filespec { · 663 unmodified lines | ||
| 1157 | 1156 | #define TOK_TWODOTS 0xa2 /* C++ token ? */ |
| 1158 | 1157 | #define TOK_TWOSHARPS 0xa3 /* ## preprocessing token */ |
| 1159 | 1158 | #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 */ | |
| 1161 | 1160 | #define TOK_SOTYPE 0xa7 /* alias of '(' for parsing sizeof (type) */ |
| 1162 | 1161 | |
| 1163 | 1162 | /* assignment operators */ |
| @@ -1253,8 +1252,8 @@ ST_FUNC void libc_free(void *ptr); · 89 unmodified lines | ||
| 1253 | 1252 | PUB_FUNC int _tcc_error_noabort(const char *fmt, ...) PRINTF_LIKE(1,2); |
| 1254 | 1253 | PUB_FUNC NORETURN void _tcc_error(const char *fmt, ...) PRINTF_LIKE(1,2); |
| 1255 | 1254 | 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) | |
| 1258 | 1257 | |
| 1259 | 1258 | /* other utilities */ |
| 1260 | 1259 | ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data); |
| @@ -153,9 +153,12 @@ ST_FUNC void tccelf_begin_file(TCCState *s1) · 152 unmodified lines | ||
| 153 | 153 | s = s1->symtab, s->reloc = s->hash, s->hash = NULL; |
| 154 | 154 | #if defined TCC_TARGET_X86_64 && defined TCC_TARGET_PE |
| 155 | 155 | s1->uw_sym = 0; |
| 156 | + s1->uw_offs = 0; | |
| 156 | 157 | #endif |
| 157 | 158 | } |
| 158 | 159 | |
| 160 | +static void update_relocs(TCCState *s1, Section *s, int *old_to_new_syms, int first_sym); | |
| 161 | + | |
| 159 | 162 | /* At the end of compilation, convert any UNDEF syms to global, and merge |
| 160 | 163 | with previously existing symbols */ |
| 161 | 164 | ST_FUNC void tccelf_end_file(TCCState *s1) |
| @@ -172,7 +175,6 @@ ST_FUNC void tccelf_end_file(TCCState *s1) · 10 unmodified lines | ||
| 172 | 175 | |
| 173 | 176 | for (i = 0; i < nb_syms; ++i) { |
| 174 | 177 | ElfSym *sym = (ElfSym*)s->data + first_sym + i; |
| 175 | − | |
| 176 | 178 | if (sym->st_shndx == SHN_UNDEF) { |
| 177 | 179 | int sym_bind = ELFW(ST_BIND)(sym->st_info); |
| 178 | 180 | int sym_type = ELFW(ST_TYPE)(sym->st_info); |
| @@ -187,26 +189,12 @@ ST_FUNC void tccelf_end_file(TCCState *s1) · 8 unmodified lines | ||
| 187 | 189 | #endif |
| 188 | 190 | sym->st_info = ELFW(ST_INFO)(sym_bind, sym_type); |
| 189 | 191 | } |
| 190 | − | |
| 191 | 192 | tr[i] = set_elf_sym(s, sym->st_value, sym->st_size, sym->st_info, |
| 192 | 193 | sym->st_other, sym->st_shndx, (char*)s->link->data + sym->st_name); |
| 193 | 194 | } |
| 194 | 195 | /* 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); | |
| 208 | 197 | tcc_free(tr); |
| 209 | − | |
| 210 | 198 | /* record text/data/bss output for -bench info */ |
| 211 | 199 | for (i = 0; i < 4; ++i) { |
| 212 | 200 | 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 | ||
| 801 | 789 | return &s1->sym_attrs[index]; |
| 802 | 790 | } |
| 803 | 791 | |
| 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) | |
| 805 | 793 | { |
| 806 | 794 | int i, type, sym_index; |
| 807 | 795 | Section *sr; |
| @@ -813,6 +801,8 @@ static void modify_reloctions_old_to_new(TCCState *s1, Section *s, int *old_to_n · 5 unmodified lines | ||
| 813 | 801 | for_each_elem(sr, 0, rel, ElfW_Rel) { |
| 814 | 802 | sym_index = ELFW(R_SYM)(rel->r_info); |
| 815 | 803 | 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) */ | |
| 816 | 806 | sym_index = old_to_new_syms[sym_index]; |
| 817 | 807 | rel->r_info = ELFW(R_INFO)(sym_index, type); |
| 818 | 808 | } |
| @@ -863,8 +853,7 @@ static void sort_syms(TCCState *s1, Section *s) · 44 unmodified lines | ||
| 863 | 853 | memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym))); |
| 864 | 854 | tcc_free(new_syms); |
| 865 | 855 | |
| 866 | − modify_reloctions_old_to_new(s1, s, old_to_new_syms); | |
| 867 | − | |
| 856 | + update_relocs(s1, s, old_to_new_syms, 0); | |
| 868 | 857 | tcc_free(old_to_new_syms); |
| 869 | 858 | } |
| 870 | 859 | |
| @@ -1012,7 +1001,7 @@ static void update_gnu_hash(TCCState *s1, Section *gnu_hash) · 141 unmodified lines | ||
| 1012 | 1001 | tcc_free(buck); |
| 1013 | 1002 | tcc_free(nextbuck); |
| 1014 | 1003 | |
| 1015 | − modify_reloctions_old_to_new(s1, dynsym, old_to_new_syms); | |
| 1004 | + update_relocs(s1, dynsym, old_to_new_syms, 0); | |
| 1016 | 1005 | |
| 1017 | 1006 | /* modify the versions */ |
| 1018 | 1007 | vs = versym_section; |
| @@ -657,8 +657,6 @@ ST_FUNC Sym *sym_find2(Sym *s, int v) · 656 unmodified lines | ||
| 657 | 657 | while (s) { |
| 658 | 658 | if (s->v == v) |
| 659 | 659 | return s; |
| 660 | − else if (s->v == -1) | |
| 661 | − return NULL; | |
| 662 | 660 | s = s->prev; |
| 663 | 661 | } |
| 664 | 662 | return NULL; |
| @@ -1398,6 +1396,7 @@ ST_FUNC void save_reg_upstack(int r, int n) · 733 unmodified lines | ||
| 1398 | 1396 | p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL; |
| 1399 | 1397 | } else { |
| 1400 | 1398 | p->r = VT_LVAL | VT_LOCAL; |
| 1399 | + p->type.t &= ~VT_ARRAY; /* cannot combine VT_LVAL with VT_ARRAY */ | |
| 1401 | 1400 | } |
| 1402 | 1401 | p->sym = NULL; |
| 1403 | 1402 | p->r2 = VT_CONST; |
| @@ -2838,14 +2837,25 @@ static int compare_types(CType *type1, CType *type2, int unqualified) · 1434 unmodified lines | ||
| 2838 | 2837 | } |
| 2839 | 2838 | } |
| 2840 | 2839 | |
| 2840 | +#define CMP_OP 'C' | |
| 2841 | +#define SHIFT_OP 'S' | |
| 2842 | + | |
| 2841 | 2843 | /* Check if OP1 and OP2 can be "combined" with operation OP, the combined |
| 2842 | 2844 | type is stored in DEST if non-null (except for pointer plus/minus) . */ |
| 2843 | 2845 | static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) |
| 2844 | 2846 | { |
| 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; | |
| 2847 | 2849 | int ret = 1; |
| 2848 | 2850 | |
| 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 | + | |
| 2849 | 2859 | type.t = VT_VOID; |
| 2850 | 2860 | type.ref = NULL; |
| 2851 | 2861 | |
| @@ -2854,7 +2864,10 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) · 2 unmodified lines | ||
| 2854 | 2864 | /* NOTE: as an extension, we accept void on only one side */ |
| 2855 | 2865 | type.t = VT_VOID; |
| 2856 | 2866 | } 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 | + } | |
| 2858 | 2871 | /* http://port70.net/~nsz/c/c99/n1256.html#6.5.15p6 */ |
| 2859 | 2872 | /* If one is a null ptr constant the result type is the other. */ |
| 2860 | 2873 | 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 | ||
| 2862 | 2875 | else if (bt1 != bt2) { |
| 2863 | 2876 | /* accept comparison or cond-expr between pointer and integer |
| 2864 | 2877 | with a warning */ |
| 2865 | − if ((op == '?' || TOK_ISCOND(op)) | |
| 2878 | + if ((op == '?' || op == CMP_OP) | |
| 2866 | 2879 | && (is_integer_btype(bt1) || is_integer_btype(bt2))) |
| 2867 | 2880 | tcc_warning("pointer/integer mismatch in %s", |
| 2868 | 2881 | op == '?' ? "conditional expression" : "comparison"); |
| @@ -2877,7 +2890,7 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) · 8 unmodified lines | ||
| 2877 | 2890 | int newquals, copied = 0; |
| 2878 | 2891 | if (pbt1 != VT_VOID && pbt2 != VT_VOID |
| 2879 | 2892 | && !compare_types(pt1, pt2, 1/*unqualif*/)) { |
| 2880 | − if (op != '?' && !TOK_ISCOND(op)) | |
| 2893 | + if (op != '?' && op != CMP_OP) | |
| 2881 | 2894 | ret = 0; |
| 2882 | 2895 | else |
| 2883 | 2896 | type_incompatibility_warning(type1, type2, |
| @@ -2918,7 +2931,7 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) · 34 unmodified lines | ||
| 2918 | 2931 | } |
| 2919 | 2932 | } |
| 2920 | 2933 | } |
| 2921 | − if (TOK_ISCOND(op)) | |
| 2934 | + if (op == CMP_OP) | |
| 2922 | 2935 | type.t = VT_SIZE_T; |
| 2923 | 2936 | } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) { |
| 2924 | 2937 | if (op != '?' || !compare_types(type1, type2, 1)) |
| @@ -2961,6 +2974,12 @@ ST_FUNC void gen_op(int op) · 36 unmodified lines | ||
| 2961 | 2974 | { |
| 2962 | 2975 | int t1, t2, bt1, bt2, t; |
| 2963 | 2976 | 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; | |
| 2964 | 2983 | |
| 2965 | 2984 | redo: |
| 2966 | 2985 | t1 = vtop[-1].type.t; |
| @@ -2980,18 +2999,19 @@ redo: · 13 unmodified lines | ||
| 2980 | 2999 | vswap(); |
| 2981 | 3000 | } |
| 2982 | 3001 | 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: | |
| 2984 | 3004 | tcc_error("invalid operand types for binary operation"); |
| 2985 | 3005 | } else if (bt1 == VT_PTR || bt2 == VT_PTR) { |
| 2986 | 3006 | /* at least one operand is a pointer */ |
| 2987 | 3007 | /* relational op: must be both pointers */ |
| 2988 | 3008 | int align; |
| 2989 | − if (TOK_ISCOND(op)) | |
| 3009 | + if (op_class == CMP_OP) | |
| 2990 | 3010 | goto std_op; |
| 2991 | 3011 | /* if both pointers, then it must be the '-' op */ |
| 2992 | 3012 | if (bt1 == VT_PTR && bt2 == VT_PTR) { |
| 2993 | 3013 | if (op != '-') |
| 2994 | − tcc_error("cannot use pointers here"); | |
| 3014 | + goto op_err; | |
| 2995 | 3015 | vpush_type_size(pointed_type(&vtop[-1].type), &align); |
| 2996 | 3016 | vtop->type.t &= ~VT_UNSIGNED; |
| 2997 | 3017 | vrott(3); |
| @@ -3002,14 +3022,15 @@ redo: · 4 unmodified lines | ||
| 3002 | 3022 | } else { |
| 3003 | 3023 | /* exactly one pointer : must be '+' or '-'. */ |
| 3004 | 3024 | if (op != '-' && op != '+') |
| 3005 | − tcc_error("cannot use pointers here"); | |
| 3025 | + goto op_err; | |
| 3006 | 3026 | /* Put pointer as first operand */ |
| 3007 | 3027 | if (bt2 == VT_PTR) { |
| 3008 | 3028 | vswap(); |
| 3009 | 3029 | t = t1, t1 = t2, t2 = t; |
| 3030 | + bt2 = bt1; | |
| 3010 | 3031 | } |
| 3011 | 3032 | #if PTR_SIZE == 4 |
| 3012 | − if ((vtop[0].type.t & VT_BTYPE) == VT_LLONG) | |
| 3033 | + if (bt2 == VT_LLONG) | |
| 3013 | 3034 | /* XXX: truncate here because gen_opl can't handle ptr + long long */ |
| 3014 | 3035 | gen_cast_s(VT_INT); |
| 3015 | 3036 | #endif |
| @@ -3039,17 +3060,15 @@ redo: · 23 unmodified lines | ||
| 3039 | 3060 | /* floats can only be used for a few operations */ |
| 3040 | 3061 | if (is_float(combtype.t) |
| 3041 | 3062 | && 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; | |
| 3050 | 3065 | } |
| 3051 | 3066 | std_op: |
| 3052 | 3067 | 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; | |
| 3053 | 3072 | /* XXX: currently, some unsigned operations are explicit, so |
| 3054 | 3073 | we modify them here */ |
| 3055 | 3074 | if (t & VT_UNSIGNED) { |
| @@ -3071,16 +3090,12 @@ redo: · 15 unmodified lines | ||
| 3071 | 3090 | vswap(); |
| 3072 | 3091 | gen_cast_s(t); |
| 3073 | 3092 | 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; | |
| 3078 | 3093 | gen_cast_s(t2); |
| 3079 | 3094 | if (is_float(t)) |
| 3080 | 3095 | gen_opif(op); |
| 3081 | 3096 | else |
| 3082 | 3097 | gen_opic(op); |
| 3083 | − if (TOK_ISCOND(op)) { | |
| 3098 | + if (op_class == CMP_OP) { | |
| 3084 | 3099 | /* relational op: the result is an int */ |
| 3085 | 3100 | vtop->type.t = VT_INT; |
| 3086 | 3101 | } else { |
| @@ -3416,13 +3431,10 @@ ST_FUNC int type_size(CType *type, int *a) · 329 unmodified lines | ||
| 3416 | 3431 | } else if (bt == VT_PTR) { |
| 3417 | 3432 | if (type->t & VT_ARRAY) { |
| 3418 | 3433 | int ts; |
| 3419 | − | |
| 3420 | 3434 | s = type->ref; |
| 3421 | 3435 | ts = type_size(&s->type, a); |
| 3422 | − | |
| 3423 | 3436 | if (ts < 0 && s->c < 0) |
| 3424 | 3437 | ts = -ts; |
| 3425 | − | |
| 3426 | 3438 | return ts * s->c; |
| 3427 | 3439 | } else { |
| 3428 | 3440 | *a = PTR_SIZE; |
| @@ -3435,18 +3447,9 @@ ST_FUNC int type_size(CType *type, int *a) · 6 unmodified lines | ||
| 3435 | 3447 | *a = LDOUBLE_ALIGN; |
| 3436 | 3448 | return LDOUBLE_SIZE; |
| 3437 | 3449 | } 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) | |
| 3448 | 3452 | *a = 4; |
| 3449 | −#endif | |
| 3450 | 3453 | #else |
| 3451 | 3454 | *a = 8; |
| 3452 | 3455 | #endif |
| @@ -3974,12 +3977,12 @@ redo: · 521 unmodified lines | ||
| 3974 | 3977 | case TOK_FASTCALL2: |
| 3975 | 3978 | case TOK_FASTCALL3: |
| 3976 | 3979 | ad->f.func_call = FUNC_FASTCALLW; |
| 3977 | − break; | |
| 3980 | + break; | |
| 3978 | 3981 | case TOK_THISCALL1: |
| 3979 | 3982 | case TOK_THISCALL2: |
| 3980 | 3983 | case TOK_THISCALL3: |
| 3981 | 3984 | ad->f.func_call = FUNC_THISCALL; |
| 3982 | − break; | |
| 3985 | + break; | |
| 3983 | 3986 | #endif |
| 3984 | 3987 | case TOK_MODE: |
| 3985 | 3988 | skip('('); |
| @@ -5714,16 +5717,12 @@ ST_FUNC void unary(void) · 1728 unmodified lines | ||
| 5714 | 5717 | case TOK_builtin_return_address: |
| 5715 | 5718 | { |
| 5716 | 5719 | int tok1 = tok; |
| 5717 | − int64_t level; | |
| 5720 | + int level; | |
| 5718 | 5721 | next(); |
| 5719 | 5722 | 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)); | |
| 5727 | 5726 | skip(')'); |
| 5728 | 5727 | type.t = VT_VOID; |
| 5729 | 5728 | mk_pointer(&type); |
| @@ -7400,12 +7399,10 @@ static void init_putz(init_params *p, unsigned long c, int size) · 1670 unmodified lines | ||
| 7400 | 7399 | } else { |
| 7401 | 7400 | vpush_helper_func(TOK_memset); |
| 7402 | 7401 | vseti(VT_LOCAL, c); |
| 7403 | −#ifdef TCC_TARGET_ARM | |
| 7404 | − vpushs(size); | |
| 7405 | − vpushi(0); | |
| 7406 | −#else | |
| 7407 | 7402 | vpushi(0); |
| 7408 | 7403 | vpushs(size); |
| 7404 | +#if defined TCC_TARGET_ARM && defined TCC_ARM_EABI | |
| 7405 | + vswap(); /* using __aeabi_memset(void*, size_t, int) */ | |
| 7409 | 7406 | #endif |
| 7410 | 7407 | gfunc_call(3); |
| 7411 | 7408 | } |
| @@ -889,7 +889,7 @@ static void pe_build_imports(struct pe_info *pe) · 888 unmodified lines | ||
| 889 | 889 | |
| 890 | 890 | dllindex = p->dll_index; |
| 891 | 891 | if (dllindex) |
| 892 | − name = tcc_basename((dllref = pe->s1->loaded_dlls[dllindex-1])->name); | |
| 892 | + name = (dllref = pe->s1->loaded_dlls[dllindex-1])->name; | |
| 893 | 893 | else |
| 894 | 894 | name = "", dllref = NULL; |
| 895 | 895 | |
| @@ -1767,6 +1767,9 @@ static int pe_load_def(TCCState *s1, int fd) · 871 unmodified lines | ||
| 1767 | 1767 | char dllname[80], *buf, *line, *p, *x, next; |
| 1768 | 1768 | |
| 1769 | 1769 | buf = tcc_load_text(fd); |
| 1770 | + if (!buf) | |
| 1771 | + return ret; | |
| 1772 | + | |
| 1770 | 1773 | for (line = buf;; ++line) { |
| 1771 | 1774 | p = get_token(&line, &next); |
| 1772 | 1775 | if (!(*p && *p != ';')) |
| @@ -1815,7 +1818,7 @@ quit: · 42 unmodified lines | ||
| 1815 | 1818 | static int pe_load_dll(TCCState *s1, int fd, const char *filename) |
| 1816 | 1819 | { |
| 1817 | 1820 | char *p, *q; |
| 1818 | − DLLReference *ref = tcc_add_dllref(s1, filename, 0); | |
| 1821 | + DLLReference *ref = tcc_add_dllref(s1, tcc_basename(filename), 0); | |
| 1819 | 1822 | if (ref->found) |
| 1820 | 1823 | return 0; |
| 1821 | 1824 | if (get_dllexports(fd, &p)) |
| @@ -92,7 +92,6 @@ static const unsigned char tok_two_chars[] = · 91 unmodified lines | ||
| 92 | 92 | '-','>', TOK_ARROW, |
| 93 | 93 | '.','.', TOK_TWODOTS, |
| 94 | 94 | '#','#', TOK_TWOSHARPS, |
| 95 | − '#','#', TOK_PPJOIN, | |
| 96 | 95 | 0 |
| 97 | 96 | }; |
| 98 | 97 | |
| @@ -137,10 +136,8 @@ ST_FUNC void expect(const char *msg) · 38 unmodified lines | ||
| 137 | 136 | |
| 138 | 137 | #define TOKSYM_TAL_SIZE (768 * 1024) /* allocator for tiny TokenSym in table_ident */ |
| 139 | 138 | #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) */ | |
| 144 | 141 | |
| 145 | 142 | typedef struct TinyAlloc { |
| 146 | 143 | unsigned limit; |
| @@ -185,8 +182,8 @@ tail_call: · 38 unmodified lines | ||
| 185 | 182 | if (!al) |
| 186 | 183 | return; |
| 187 | 184 | #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, | |
| 190 | 187 | (al->peak_p - al->buffer) * 100.0 / al->size); |
| 191 | 188 | #endif |
| 192 | 189 | #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 | ||
| 345 | 342 | size = cstr->size + 1; |
| 346 | 343 | if (size > cstr->size_allocated) |
| 347 | 344 | cstr_realloc(cstr, size); |
| 348 | − ((unsigned char *)cstr->data)[size - 1] = ch; | |
| 345 | + cstr->data[size - 1] = ch; | |
| 349 | 346 | cstr->size = size; |
| 350 | 347 | } |
| 351 | 348 | |
| @@ -368,6 +365,7 @@ ST_INLN void cstr_u8cat(CString *cstr, int ch) · 16 unmodified lines | ||
| 368 | 365 | cstr_cat(cstr, buf, e - buf); |
| 369 | 366 | } |
| 370 | 367 | |
| 368 | +/* add string of 'len', or of its len/len+1 when 'len' == -1/0 */ | |
| 371 | 369 | ST_FUNC void cstr_cat(CString *cstr, const char *str, int len) |
| 372 | 370 | { |
| 373 | 371 | int size; |
| @@ -376,7 +374,7 @@ ST_FUNC void cstr_cat(CString *cstr, const char *str, int len) · 2 unmodified lines | ||
| 376 | 374 | size = cstr->size + len; |
| 377 | 375 | if (size > cstr->size_allocated) |
| 378 | 376 | cstr_realloc(cstr, size); |
| 379 | − memmove(((unsigned char *)cstr->data) + cstr->size, str, len); | |
| 377 | + memmove(cstr->data + cstr->size, str, len); | |
| 380 | 378 | cstr->size = size; |
| 381 | 379 | } |
| 382 | 380 | |
| @@ -387,7 +385,7 @@ ST_FUNC void cstr_wccat(CString *cstr, int ch) · 4 unmodified lines | ||
| 387 | 385 | size = cstr->size + sizeof(nwchar_t); |
| 388 | 386 | if (size > cstr->size_allocated) |
| 389 | 387 | 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; | |
| 391 | 389 | cstr->size = size; |
| 392 | 390 | } |
| 393 | 391 | |
| @@ -418,7 +416,7 @@ ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap) · 24 unmodified lines | ||
| 418 | 416 | cstr_realloc(cstr, size); |
| 419 | 417 | size = cstr->size_allocated - cstr->size; |
| 420 | 418 | 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); | |
| 422 | 420 | va_end(v); |
| 423 | 421 | if (len >= 0 && len < size) |
| 424 | 422 | break; |
| @@ -1920,7 +1918,8 @@ ST_FUNC void preprocess(int is_bof) · 1495 unmodified lines | ||
| 1920 | 1918 | if (file->fd > 0) |
| 1921 | 1919 | total_lines += file->line_num - n; |
| 1922 | 1920 | file->line_num = n; |
| 1923 | − break; | |
| 1921 | + goto ignore; /* skip optional level number */ | |
| 1922 | + | |
| 1924 | 1923 | case TOK_ERROR: |
| 1925 | 1924 | case TOK_WARNING: |
| 1926 | 1925 | q = buf; |
| @@ -3070,12 +3069,13 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) · 1143 unmodified lines | ||
| 3070 | 3069 | /* handle the '##' operator. return the resulting string (which must be freed). */ |
| 3071 | 3070 | static inline int *macro_twosharps(const int *ptr0) |
| 3072 | 3071 | { |
| 3073 | − int t1, t2, n; | |
| 3072 | + int t1, t2, n, l; | |
| 3074 | 3073 | CValue cv1, cv2; |
| 3075 | 3074 | TokenString macro_str1; |
| 3076 | 3075 | const int *ptr; |
| 3077 | 3076 | |
| 3078 | 3077 | tok_str_new(¯o_str1); |
| 3078 | + cstr_reset(&tokcstr); | |
| 3079 | 3079 | for (ptr = ptr0;;) { |
| 3080 | 3080 | TOK_GET(&t1, &ptr, &cv1); |
| 3081 | 3081 | if (t1 == 0) |
| @@ -3090,29 +3090,31 @@ static inline int *macro_twosharps(const int *ptr0) · 8 unmodified lines | ||
| 3090 | 3090 | while ((t2 = *++ptr) == ' ' || t2 == TOK_PPJOIN) |
| 3091 | 3091 | ; |
| 3092 | 3092 | TOK_GET(&t2, &ptr, &cv2); |
| 3093 | − if (t1 == TOK_PLCHLDR && t2 == TOK_PLCHLDR) | |
| 3093 | + if (t2 == TOK_PLCHLDR) | |
| 3094 | 3094 | continue; |
| 3095 | − cstr_reset(&tokcstr); | |
| 3096 | − if (t1 != TOK_PLCHLDR) | |
| 3095 | + if (t1 != TOK_PLCHLDR) { | |
| 3097 | 3096 | 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); | |
| 3103 | 3103 | tcc_open_bf(tcc_state, ":paste:", tokcstr.size); |
| 3104 | 3104 | memcpy(file->buffer, tokcstr.data, tokcstr.size); |
| 3105 | 3105 | 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(¯o_str1, tok, &tokc); | |
| 3109 | + if (*file->buf_ptr == 0) | |
| 3110 | + break; | |
| 3111 | + tok_str_add(¯o_str1, ' '); | |
| 3112 | + l = file->buf_ptr - file->buffer; | |
| 3110 | 3113 | tcc_warning("pasting \"%.*s\" and \"%s\" does not give a valid" |
| 3111 | − " preprocessing token", n, file->buffer, file->buffer + n); | |
| 3112 | − tok_str_add2(¯o_str1, t1, &cv1); | |
| 3113 | − t1 = t2, cv1 = cv2; | |
| 3114 | + " preprocessing token", l - n, file->buffer + n, file->buf_ptr); | |
| 3114 | 3115 | } |
| 3115 | 3116 | tcc_close(); |
| 3117 | + cstr_reset(&tokcstr); | |
| 3116 | 3118 | } |
| 3117 | 3119 | if (t1 != TOK_PLCHLDR) |
| 3118 | 3120 | tok_str_add2(¯o_str1, t1, &cv1); |
| @@ -3450,9 +3452,8 @@ redo: · 331 unmodified lines | ||
| 3450 | 3452 | /* do nothing */ |
| 3451 | 3453 | } else { |
| 3452 | 3454 | ++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 == '\\') { | |
| 3456 | 3457 | if (!(parse_flags & PARSE_FLAG_ACCEPT_STRAYS)) |
| 3457 | 3458 | tcc_error("stray '\\' in program"); |
| 3458 | 3459 | } |
| @@ -483,4 +483,11 @@ struct A { · 482 unmodified lines | ||
| 483 | 483 | # if X(1,2) //undefined function macro |
| 484 | 484 | # endif |
| 485 | 485 | |
| 486 | +#elif defined test_pointer_plus_double | |
| 487 | + | |
| 488 | +int *invalid_operation(int *p, double d) | |
| 489 | +{ | |
| 490 | + return p + d; | |
| 491 | +} | |
| 492 | + | |
| 486 | 493 | #endif |
| @@ -237,3 +237,6 @@ arg[1] = "Y" · 236 unmodified lines | ||
| 237 | 237 | |
| 238 | 238 | [test_pp_error_2] |
| 239 | 239 | 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 | |
| @@ -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 | −} | |
| @@ -25,7 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #ifdef NEED_RELOC_TYPE |
| 26 | 26 | /* Returns 1 for a code relocation, 0 for a data relocation. For unknown |
| 27 | 27 | relocations, returns -1. */ |
| 28 | −int code_reloc (int reloc_type) | |
| 28 | +ST_FUNC int code_reloc (int reloc_type) | |
| 29 | 29 | { |
| 30 | 30 | switch (reloc_type) { |
| 31 | 31 | case R_X86_64_32: |
| @@ -64,7 +64,7 @@ int code_reloc (int reloc_type) · 32 unmodified lines | ||
| 64 | 64 | /* Returns an enumerator to describe whether and when the relocation needs a |
| 65 | 65 | GOT and/or PLT entry to be created. See tcc.h for a description of the |
| 66 | 66 | different values. */ |
| 67 | −int gotplt_entry_type (int reloc_type) | |
| 67 | +ST_FUNC int gotplt_entry_type (int reloc_type) | |
| 68 | 68 | { |
| 69 | 69 | switch (reloc_type) { |
| 70 | 70 | case R_X86_64_GLOB_DAT: |
| @@ -186,7 +186,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 115 unmodified lines | ||
| 186 | 186 | #endif |
| 187 | 187 | #endif |
| 188 | 188 | |
| 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) | |
| 190 | 190 | { |
| 191 | 191 | int sym_index, esym_index; |
| 192 | 192 | |