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