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
6464 if (!sym || sym->r) {
6565 /* if the last label is defined, then define a new one */
6666 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;
6868 }
6969 }
7070 pe->v = 0;
@@ -123,7 +123,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe) · 52 unmodified lines
123123 if (!sym) {
124124 sym = label_push(&s1->asm_labels, tok, 0);
125125 /* NOTE: by default, the symbol is global */
126− sym->type.t = VT_VOID;
126+ sym->type.t = VT_VOID | VT_EXTERN;
127127 }
128128 if (sym->r == SHN_ABS) {
129129 /* 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
317317
318318 /* NOTE: the same name space as C labels is used to avoid using too
319319 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,
321321 int sh_num, int value)
322322 {
323323 Sym *sym;
324324
325325 sym = label_find(label);
326326 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)) {
328331 /* the label is already defined */
329332 if (!is_local) {
330333 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
337340 } else {
338341 new_label:
339342 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;
341347 }
342348 sym->r = sh_num;
343349 sym->jnext = value;
350+ return sym;
344351 }
345352
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)
347354 {
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);
349371 }
350372
351373 static void asm_free_labels(TCCState *st)
@@ -356,6 +378,7 @@ static void asm_free_labels(TCCState *st) · 4 unmodified lines
356378 for(s = st->asm_labels; s != NULL; s = s1) {
357379 s1 = s->prev;
358380 /* define symbol value in object file */
381+ s->type.t &= ~VT_EXTERN;
359382 if (s->r) {
360383 if (s->r == SHN_ABS)
361384 sec = SECTION_ABS;
@@ -608,6 +631,15 @@ static void asm_parse_directive(TCCState *s1) · 246 unmodified lines
608631 goto zero_pad;
609632 }
610633 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;
611643 case TOK_ASMDIR_globl:
612644 case TOK_ASMDIR_global:
613645 case TOK_ASMDIR_weak:
@@ -620,7 +652,7 @@ static void asm_parse_directive(TCCState *s1) · 6 unmodified lines
620652 sym = label_find(tok);
621653 if (!sym) {
622654 sym = label_push(&s1->asm_labels, tok, 0);
623− sym->type.t = VT_VOID;
655+ sym->type.t = VT_VOID | VT_EXTERN;
624656 }
625657 if (tok1 != TOK_ASMDIR_hidden)
626658 sym->type.t &= ~VT_STATIC;
@@ -743,7 +775,7 @@ static void asm_parse_directive(TCCState *s1) · 116 unmodified lines
743775 sym = label_find(tok);
744776 if (!sym) {
745777 sym = label_push(&s1->asm_labels, tok, 0);
746− sym->type.t = VT_VOID;
778+ sym->type.t = VT_VOID | VT_EXTERN;
747779 }
748780
749781 next();
@@ -875,6 +907,7 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess) · 125 unmodified lines
875907 } else if (tok >= TOK_ASMDIR_FIRST && tok <= TOK_ASMDIR_LAST) {
876908 asm_parse_directive(s1);
877909 } else if (tok == TOK_PPNUM) {
910+ Sym *sym;
878911 const char *p;
879912 int n;
880913 p = tokc.str.data;
@@ -882,7 +915,9 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess) · 1 unmodified line
882915 if (*p != '\0')
883916 expect("':'");
884917 /* 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;
886921 next();
887922 skip(':');
888923 goto redo;
@@ -898,18 +933,16 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess) · 9 unmodified lines
898933 sym = label_find(opcode);
899934 if (!sym) {
900935 sym = label_push(&s1->asm_labels, opcode, 0);
901− sym->type.t = VT_VOID;
936+ sym->type.t = VT_VOID | VT_EXTERN;
902937 }
903938 }
904939 /* new label */
905− asm_new_label(s1, opcode, 0);
940+ sym = asm_new_label(s1, opcode, 0);
941+ sym->type.t &= ~VT_EXTERN;
906942 next();
907943 goto redo;
908944 } else if (tok == '=') {
909− int n;
910− next();
911− n = asm_int_expr(s1);
912− asm_new_label1(s1, opcode, 0, SHN_ABS, n);
945+ set_symbol(s1, opcode);
913946 goto redo;
914947 } else {
915948 asm_opcode(s1, opcode);
tcctok.h+1−0
@@ -308,6 +308,7 @@ · 307 unmodified lines
308308 DEF_ASMDIR(align)
309309 DEF_ASMDIR(balign)
310310 DEF_ASMDIR(p2align)
311+ DEF_ASMDIR(set)
311312 DEF_ASMDIR(skip)
312313 DEF_ASMDIR(space)
313314 DEF_ASMDIR(string)
tests/asmtest.S+11−0
@@ -824,6 +824,17 @@ nop · 823 unmodified lines
824824 .skip (-((4b-3b) > 0) * 2) , 0x90
825825 .popsection
826826
827+.globl overrideme
828+.weak overrideme
829+ nop
830+.globl notimplemented
831+notimplemented:
832+ ret
833+.set overrideme, notimplemented
834+overrideme = notimplemented
835+overrideme:
836+ ret
837+
827838 movd %esi, %mm1
828839 movd %edi, %xmm2
829840 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