History

tccasm: Implement .set sym, expr

That, as well as "sym = expr", if expr contains symbols. Slightly tricky because a definition from .set is overridable, whereas proper definitions aren't. This doesn't yet allow using this for override tricks from C and global asm blocks because the symbol tables from C and asm are separate.

Michael Matz committed 10 years ago

Commit c4edfb41 parent 34fc6433 files · +61 −16Browse files

Unified · Split

3 files
  1. tccasm.c +49 −16
  2. tcctok.h +1 −0
  3. tests/asmtest.S +11 −0
tccasm.c+49−16
@@ -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 too318/* 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 */
320static void asm_new_label1(TCCState *s1, int label, int is_local,320static 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
346static void asm_new_label(TCCState *s1, int label, int is_local)353static 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. */
360static 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
351static void asm_free_labels(TCCState *st)373static 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);
tcctok.h+1−0
@@ -308,6 +308,7 @@ · 307 unmodified lines
308 DEF_ASMDIR(align)308 DEF_ASMDIR(align)
309 DEF_ASMDIR(balign)309 DEF_ASMDIR(balign)
310 DEF_ASMDIR(p2align)310 DEF_ASMDIR(p2align)
311 DEF_ASMDIR(set)
311 DEF_ASMDIR(skip)312 DEF_ASMDIR(skip)
312 DEF_ASMDIR(space)313 DEF_ASMDIR(space)
313 DEF_ASMDIR(string)314 DEF_ASMDIR(string)
tests/asmtest.S+11−0
@@ -824,6 +824,17 @@ nop · 823 unmodified lines
824.skip (-((4b-3b) > 0) * 2) , 0x90824.skip (-((4b-3b) > 0) * 2) , 0x90
825.popsection825.popsection
826 826
827.globl overrideme
828.weak overrideme
829 nop
830.globl notimplemented
831notimplemented:
832 ret
833.set overrideme, notimplemented
834overrideme = notimplemented
835overrideme:
836 ret
837
827 movd %esi, %mm1838 movd %esi, %mm1
828 movd %edi, %xmm2839 movd %edi, %xmm2
829 movd (%ebx), %mm3840 movd (%ebx), %mm3

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

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

Repository code

Go to file
t