| @@ -64,7 +64,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe) · 63 unmodified lines |
| 64 | if (!sym || sym->r) { | 64 | if (!sym || sym->r) { |
| 65 | /* if the last label is defined, then define a new one */ | 65 | /* if the last label is defined, then define a new one */ |
| 66 | sym = label_push(&s1->asm_labels, label, 0); | 66 | sym = label_push(&s1->asm_labels, label, 0); |
| 67 | sym->type.t = VT_STATIC | VT_VOID; | 67 | sym->type.t = VT_STATIC | VT_VOID | VT_EXTERN; |
| 68 | } | 68 | } |
| 69 | } | 69 | } |
| 70 | pe->v = 0; | 70 | pe->v = 0; |
| @@ -123,7 +123,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe) · 52 unmodified lines |
| 123 | if (!sym) { | 123 | if (!sym) { |
| 124 | sym = label_push(&s1->asm_labels, tok, 0); | 124 | sym = label_push(&s1->asm_labels, tok, 0); |
| 125 | /* NOTE: by default, the symbol is global */ | 125 | /* NOTE: by default, the symbol is global */ |
| 126 | sym->type.t = VT_VOID; | 126 | sym->type.t = VT_VOID | VT_EXTERN; |
| 127 | } | 127 | } |
| 128 | if (sym->r == SHN_ABS) { | 128 | if (sym->r == SHN_ABS) { |
| 129 | /* if absolute symbol, no need to put a symbol value */ | 129 | /* if absolute symbol, no need to put a symbol value */ |
| @@ -317,14 +317,17 @@ ST_FUNC int asm_int_expr(TCCState *s1) · 187 unmodified lines |
| 317 | | 317 | |
| 318 | /* NOTE: the same name space as C labels is used to avoid using too | 318 | /* NOTE: the same name space as C labels is used to avoid using too |
| 319 | much memory when storing labels in TokenStrings */ | 319 | much memory when storing labels in TokenStrings */ |
| 320 | static void asm_new_label1(TCCState *s1, int label, int is_local, | 320 | static Sym* asm_new_label1(TCCState *s1, int label, int is_local, |
| 321 | int sh_num, int value) | 321 | int sh_num, int value) |
| 322 | { | 322 | { |
| 323 | Sym *sym; | 323 | Sym *sym; |
| 324 | | 324 | |
| 325 | sym = label_find(label); | 325 | sym = label_find(label); |
| 326 | if (sym) { | 326 | if (sym) { |
| 327 | if (sym->r) { | 327 | /* A VT_EXTERN symbol, even if it has a section is considered |
| | 328 | overridable. This is how we "define" .set targets. Real |
| | 329 | definitions won't have VT_EXTERN set. */ |
| | 330 | if (sym->r && !(sym->type.t & VT_EXTERN)) { |
| 328 | /* the label is already defined */ | 331 | /* the label is already defined */ |
| 329 | if (!is_local) { | 332 | if (!is_local) { |
| 330 | tcc_error("assembler label '%s' already defined", | 333 | tcc_error("assembler label '%s' already defined", |
| @@ -337,15 +340,34 @@ static void asm_new_label1(TCCState *s1, int label, int is_local, · 6 unmodified lines |
| 337 | } else { | 340 | } else { |
| 338 | new_label: | 341 | new_label: |
| 339 | sym = label_push(&s1->asm_labels, label, 0); | 342 | sym = label_push(&s1->asm_labels, label, 0); |
| 340 | sym->type.t = VT_STATIC | VT_VOID; | 343 | /* If we need a symbol to hold a value, mark it as |
| | 344 | tentative only (for .set). If this is for a real label |
| | 345 | we'll remove VT_EXTERN. */ |
| | 346 | sym->type.t = VT_STATIC | VT_VOID | VT_EXTERN; |
| 341 | } | 347 | } |
| 342 | sym->r = sh_num; | 348 | sym->r = sh_num; |
| 343 | sym->jnext = value; | 349 | sym->jnext = value; |
| | 350 | return sym; |
| 344 | } | 351 | } |
| 345 | | 352 | |
| 346 | static void asm_new_label(TCCState *s1, int label, int is_local) | 353 | static Sym* asm_new_label(TCCState *s1, int label, int is_local) |
| 347 | { | 354 | { |
| 348 | asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind); | 355 | return asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind); |
| | 356 | } |
| | 357 | |
| | 358 | /* Set the value of LABEL to that of some expression (possibly |
| | 359 | involving other symbols). LABEL can be overwritten later still. */ |
| | 360 | static Sym* set_symbol(TCCState *s1, int label) |
| | 361 | { |
| | 362 | Sym *sym; |
| | 363 | long n; |
| | 364 | ExprValue e; |
| | 365 | next(); |
| | 366 | asm_expr(s1, &e); |
| | 367 | n = e.v; |
| | 368 | if (e.sym) |
| | 369 | n += e.sym->jnext; |
| | 370 | return asm_new_label1(s1, label, 0, e.sym ? e.sym->r : SHN_ABS, n); |
| 349 | } | 371 | } |
| 350 | | 372 | |
| 351 | static void asm_free_labels(TCCState *st) | 373 | static void asm_free_labels(TCCState *st) |
| @@ -356,6 +378,7 @@ static void asm_free_labels(TCCState *st) · 4 unmodified lines |
| 356 | for(s = st->asm_labels; s != NULL; s = s1) { | 378 | for(s = st->asm_labels; s != NULL; s = s1) { |
| 357 | s1 = s->prev; | 379 | s1 = s->prev; |
| 358 | /* define symbol value in object file */ | 380 | /* define symbol value in object file */ |
| | 381 | s->type.t &= ~VT_EXTERN; |
| 359 | if (s->r) { | 382 | if (s->r) { |
| 360 | if (s->r == SHN_ABS) | 383 | if (s->r == SHN_ABS) |
| 361 | sec = SECTION_ABS; | 384 | sec = SECTION_ABS; |
| @@ -608,6 +631,15 @@ static void asm_parse_directive(TCCState *s1) · 246 unmodified lines |
| 608 | goto zero_pad; | 631 | goto zero_pad; |
| 609 | } | 632 | } |
| 610 | break; | 633 | break; |
| | 634 | case TOK_ASMDIR_set: |
| | 635 | next(); |
| | 636 | tok1 = tok; |
| | 637 | next(); |
| | 638 | /* Also accept '.set stuff', but don't do anything with this. |
| | 639 | It's used in GAS to set various features like '.set mips16'. */ |
| | 640 | if (tok == ',') |
| | 641 | set_symbol(s1, tok1); |
| | 642 | break; |
| 611 | case TOK_ASMDIR_globl: | 643 | case TOK_ASMDIR_globl: |
| 612 | case TOK_ASMDIR_global: | 644 | case TOK_ASMDIR_global: |
| 613 | case TOK_ASMDIR_weak: | 645 | case TOK_ASMDIR_weak: |
| @@ -620,7 +652,7 @@ static void asm_parse_directive(TCCState *s1) · 6 unmodified lines |
| 620 | sym = label_find(tok); | 652 | sym = label_find(tok); |
| 621 | if (!sym) { | 653 | if (!sym) { |
| 622 | sym = label_push(&s1->asm_labels, tok, 0); | 654 | sym = label_push(&s1->asm_labels, tok, 0); |
| 623 | sym->type.t = VT_VOID; | 655 | sym->type.t = VT_VOID | VT_EXTERN; |
| 624 | } | 656 | } |
| 625 | if (tok1 != TOK_ASMDIR_hidden) | 657 | if (tok1 != TOK_ASMDIR_hidden) |
| 626 | sym->type.t &= ~VT_STATIC; | 658 | sym->type.t &= ~VT_STATIC; |
| @@ -743,7 +775,7 @@ static void asm_parse_directive(TCCState *s1) · 116 unmodified lines |
| 743 | sym = label_find(tok); | 775 | sym = label_find(tok); |
| 744 | if (!sym) { | 776 | if (!sym) { |
| 745 | sym = label_push(&s1->asm_labels, tok, 0); | 777 | sym = label_push(&s1->asm_labels, tok, 0); |
| 746 | sym->type.t = VT_VOID; | 778 | sym->type.t = VT_VOID | VT_EXTERN; |
| 747 | } | 779 | } |
| 748 | | 780 | |
| 749 | next(); | 781 | next(); |
| @@ -875,6 +907,7 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess) · 125 unmodified lines |
| 875 | } else if (tok >= TOK_ASMDIR_FIRST && tok <= TOK_ASMDIR_LAST) { | 907 | } else if (tok >= TOK_ASMDIR_FIRST && tok <= TOK_ASMDIR_LAST) { |
| 876 | asm_parse_directive(s1); | 908 | asm_parse_directive(s1); |
| 877 | } else if (tok == TOK_PPNUM) { | 909 | } else if (tok == TOK_PPNUM) { |
| | 910 | Sym *sym; |
| 878 | const char *p; | 911 | const char *p; |
| 879 | int n; | 912 | int n; |
| 880 | p = tokc.str.data; | 913 | p = tokc.str.data; |
| @@ -882,7 +915,9 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess) · 1 unmodified line |
| 882 | if (*p != '\0') | 915 | if (*p != '\0') |
| 883 | expect("':'"); | 916 | expect("':'"); |
| 884 | /* new local label */ | 917 | /* new local label */ |
| 885 | asm_new_label(s1, asm_get_local_label_name(s1, n), 1); | 918 | sym = asm_new_label(s1, asm_get_local_label_name(s1, n), 1); |
| | 919 | /* Remove the marker for tentative definitions. */ |
| | 920 | sym->type.t &= ~VT_EXTERN; |
| 886 | next(); | 921 | next(); |
| 887 | skip(':'); | 922 | skip(':'); |
| 888 | goto redo; | 923 | goto redo; |
| @@ -898,18 +933,16 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess) · 9 unmodified lines |
| 898 | sym = label_find(opcode); | 933 | sym = label_find(opcode); |
| 899 | if (!sym) { | 934 | if (!sym) { |
| 900 | sym = label_push(&s1->asm_labels, opcode, 0); | 935 | sym = label_push(&s1->asm_labels, opcode, 0); |
| 901 | sym->type.t = VT_VOID; | 936 | sym->type.t = VT_VOID | VT_EXTERN; |
| 902 | } | 937 | } |
| 903 | } | 938 | } |
| 904 | /* new label */ | 939 | /* new label */ |
| 905 | asm_new_label(s1, opcode, 0); | 940 | sym = asm_new_label(s1, opcode, 0); |
| | 941 | sym->type.t &= ~VT_EXTERN; |
| 906 | next(); | 942 | next(); |
| 907 | goto redo; | 943 | goto redo; |
| 908 | } else if (tok == '=') { | 944 | } else if (tok == '=') { |
| 909 | int n; | 945 | set_symbol(s1, opcode); |
| 910 | next(); | | |
| 911 | n = asm_int_expr(s1); | | |
| 912 | asm_new_label1(s1, opcode, 0, SHN_ABS, n); | | |
| 913 | goto redo; | 946 | goto redo; |
| 914 | } else { | 947 | } else { |
| 915 | asm_opcode(s1, opcode); | 948 | asm_opcode(s1, opcode); |