History

Reinstate attribute alias handling

commit 2a0167a merged alias and asm symbol renaming, but broke semantics of aliases, see testcase. Basically the difference between the two is that an asm rename doesn't generate a new symbol, i.e. with int foo __asm__("bar"); all source reference to 'foo' will be to 'bar', nothing of the name 'foo' will remain in the object file, and for instance reference to 'foo' from other compilation units won't be resolved to this one. Aliases OTOH create an additional symbol. With: void target (void) { return; } void afunc (void) __attribute__((alias("target"))); reference to 'afunc' will remain 'afunc' in the object file. It will generate two symbols, 'afunc' and 'target' referring to the same entity. This difference matters if other compilation units make references to 'afunc'. A side requirement of this is that for alias to work that the target symbol needs to be defined in the same unit. For TCC we even require a stricter variant: it must be defined before the alias is created. Now, with this I merely re-instated the old flow of events before above commit. It didn't seem useful anymore to place both names in the asm_label member of attributes, and the asm_label member of Sym now again only needs the hold the __asm__ rename. It also follows that tcc_predefs.h can't make use of attribute alias to e.g. map __builtin_memcpy to __bound_memcpy (simply because the latter isn't defined in all units), but rather must use __asm__ renaming, which in turn means that the underscore handling needs to be done by hand.

Michael Matz committed 6 years ago

Commit 352e1d01 parent 727e24c7 files · +80 −10Browse files

Unified · Split

7 files
  1. tcc.h +1 −0
  2. tccgen.c +20 −6
  3. tccpp.c +9 −4
  4. tests/tests2/120+_alias.c +15 −0
  5. tests/tests2/120_alias.c +25 −0
  6. tests/tests2/120_alias.expect +5 −0
  7. tests/tests2/Makefile +5 −0
tcc.h+1−0
@@ -643,6 +643,7 @@ typedef struct AttributeDef { · 642 unmodified lines
643 struct FuncAttr f;643 struct FuncAttr f;
644 struct Section *section;644 struct Section *section;
645 Sym *cleanup_func;645 Sym *cleanup_func;
646 int alias_target; /* token */
646 int asm_label; /* associated asm label */647 int asm_label; /* associated asm label */
647 char attr_mode; /* __attribute__((__mode__(...))) */648 char attr_mode; /* __attribute__((__mode__(...))) */
648} AttributeDef;649} AttributeDef;
tccgen.c+20−6
@@ -939,10 +939,8 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, · 938 unmodified lines
939#endif939#endif
940 940
941 if (sym->asm_label) {941 if (sym->asm_label) {
942 name = get_tok_str(sym->asm_label & ~SYM_FIELD, NULL);942 name = get_tok_str(sym->asm_label, NULL);
943 /* with SYM_FIELD it was __attribute__((alias("..."))) actually */943 can_add_underscore = 0;
944 if (!(sym->asm_label & SYM_FIELD))
945 can_add_underscore = 0;
946 }944 }
947 945
948 if (tcc_state->leading_underscore && can_add_underscore) {946 if (tcc_state->leading_underscore && can_add_underscore) {
@@ -1524,6 +1522,8 @@ static void merge_attr(AttributeDef *ad, AttributeDef *ad1) · 575 unmodified lines
1524 1522
1525 if (ad1->section)1523 if (ad1->section)
1526 ad->section = ad1->section;1524 ad->section = ad1->section;
1525 if (ad1->alias_target)
1526 ad->alias_target = ad1->alias_target;
1527 if (ad1->asm_label)1527 if (ad1->asm_label)
1528 ad->asm_label = ad1->asm_label;1528 ad->asm_label = ad1->asm_label;
1529 if (ad1->attr_mode)1529 if (ad1->attr_mode)
@@ -4147,8 +4147,8 @@ redo: · 2617 unmodified lines
4147 case TOK_ALIAS2:4147 case TOK_ALIAS2:
4148 skip('(');4148 skip('(');
4149 parse_mult_str(&astr, "alias(\"target\")");4149 parse_mult_str(&astr, "alias(\"target\")");
4150 ad->asm_label = /* save string as token, for later */4150 ad->alias_target = /* save string as token, for later */
4151 tok_alloc((char*)astr.data, astr.size-1)->tok | SYM_FIELD;4151 tok_alloc((char*)astr.data, astr.size-1)->tok;
4152 skip(')');4152 skip(')');
4153 cstr_free(&astr);4153 cstr_free(&astr);
4154 break;4154 break;
@@ -8459,6 +8459,20 @@ found: · 4304 unmodified lines
8459 /* external variable or function */8459 /* external variable or function */
8460 type.t |= VT_EXTERN;8460 type.t |= VT_EXTERN;
8461 sym = external_sym(v, &type, r, &ad);8461 sym = external_sym(v, &type, r, &ad);
8462 if (ad.alias_target) {
8463 /* Aliases need to be emitted when their target
8464 symbol is emitted, even if perhaps unreferenced.
8465 We only support the case where the base is
8466 already defined, otherwise we would need
8467 deferring to emit the aliases until the end of
8468 the compile unit. */
8469 Sym *alias_target = sym_find(ad.alias_target);
8470 ElfSym *esym = elfsym(alias_target);
8471 if (!esym)
8472 tcc_error("unsupported forward __alias__ attribute");
8473 put_extern_sym2(sym, esym->st_shndx,
8474 esym->st_value, esym->st_size, 0);
8475 }
8462 } else {8476 } else {
8463 if (type.t & VT_STATIC)8477 if (type.t & VT_STATIC)
8464 r |= VT_CONST;8478 r |= VT_CONST;
tccpp.c+9−4
@@ -3673,16 +3673,21 @@ static void tcc_predefs(CString *cstr) · 3672 unmodified lines
3673 "#ifndef __builtin_va_copy\n"3673 "#ifndef __builtin_va_copy\n"
3674 "#define __builtin_va_copy(dest,src) (dest)=(src)\n"3674 "#define __builtin_va_copy(dest,src) (dest)=(src)\n"
3675 "#endif\n"3675 "#endif\n"
3676 "#ifdef __leading_underscore\n"
3677 "#define RENAME(X) __asm__(\"_\"X)\n"
3678 "#else\n"
3679 "#define RENAME(X) __asm__(X)\n"
3680 "#endif\n"
3676 /* TCC BBUILTIN AND BOUNDS ALIASES */3681 /* TCC BBUILTIN AND BOUNDS ALIASES */
3677 "#ifdef __BOUNDS_CHECKING_ON\n"3682 "#ifdef __BOUNDS_CHECKING_ON\n"
3678 "#define __BUILTINBC(ret,name,params) ret __builtin_##name params __attribute__((alias(\"__bound_\"#name)));\n"3683 "#define __BUILTINBC(ret,name,params) ret __builtin_##name params RENAME(\"__bound_\"#name);\n"
3679 "#define __BOUND(ret,name,params) ret name params __attribute__((alias(\"__bound_\"#name)));\n"3684 "#define __BOUND(ret,name,params) ret name params RENAME(\"__bound_\"#name);\n"
3680 "#else\n"3685 "#else\n"
3681 "#define __BUILTINBC(ret,name,params) ret __builtin_##name params __attribute__((alias(#name)));\n"3686 "#define __BUILTINBC(ret,name,params) ret __builtin_##name params RENAME(#name);\n"
3682 "#define __BOUND(ret,name,params)\n"3687 "#define __BOUND(ret,name,params)\n"
3683 "#endif\n"3688 "#endif\n"
3684 "#define __BOTH(ret,name,params) __BUILTINBC(ret,name,params)__BOUND(ret,name,params)\n"3689 "#define __BOTH(ret,name,params) __BUILTINBC(ret,name,params)__BOUND(ret,name,params)\n"
3685 "#define __BUILTIN(ret,name,params) ret __builtin_##name params __attribute__((alias(\"\"#name)));\n"3690 "#define __BUILTIN(ret,name,params) ret __builtin_##name params RENAME(#name);\n"
3686 "__BOTH(void*,memcpy,(void*,const void*,__SIZE_TYPE__))\n"3691 "__BOTH(void*,memcpy,(void*,const void*,__SIZE_TYPE__))\n"
3687 "__BOTH(void*,memmove,(void*,const void*,__SIZE_TYPE__))\n"3692 "__BOTH(void*,memmove,(void*,const void*,__SIZE_TYPE__))\n"
3688 "__BOTH(void*,memset,(void*,int,__SIZE_TYPE__))\n"3693 "__BOTH(void*,memset,(void*,int,__SIZE_TYPE__))\n"
tests/tests2/120+_alias.c+15−0
@@ -0,0 +1,15 @@
1extern int printf (const char *, ...);
2extern void target(void);
3extern void alias_for_target(void);
4extern void asm_for_target(void);
5
6void inunit2(void);
7
8void inunit2(void)
9{
10 target();
11 alias_for_target();
12 /* This symbol is not supposed to be available in this unit:
13 asm_for_target();
14 */
15}
tests/tests2/120_alias.c+25−0
@@ -0,0 +1,25 @@
1/* Check semantics of various constructs to generate renamed symbols. */
2extern int printf (const char *, ...);
3void target(void);
4void target(void) {
5 printf("in target function\n");
6}
7
8void alias_for_target(void) __attribute__((alias("target")));
9void asm_for_target(void) __asm__("target");
10
11/* This is not supposed to compile, alias targets must be defined in the
12 same unit. In TCC they even must be defined before the reference
13void alias_for_undef(void) __attribute__((alias("undefined")));
14*/
15
16extern void inunit2(void);
17
18int main(void)
19{
20 target();
21 alias_for_target();
22 asm_for_target();
23 inunit2();
24 return 0;
25}
tests/tests2/120_alias.expect+5−0
@@ -0,0 +1,5 @@
1in target function
2in target function
3in target function
4in target function
5in target function
tests/tests2/Makefile+5−0
@@ -74,6 +74,11 @@ GEN-ALWAYS = · 73 unmodified lines
74104_inline.test : FLAGS += $(subst 104,104+,$1)74104_inline.test : FLAGS += $(subst 104,104+,$1)
75104_inline.test : GEN = $(GEN-TCC)75104_inline.test : GEN = $(GEN-TCC)
76 76
77# this test needs two files, and we want to invoke the linker
78120_alias.test : FLAGS += $(subst 120,120+,$1)
79120_alias.test : GEN = $(GEN-TCC)
80120_alias.test : NORUN = true
81
77# this test needs pthread82# this test needs pthread
78106_pthread.test: FLAGS += -pthread83106_pthread.test: FLAGS += -pthread
79106_pthread.test: NORUN = true84106_pthread.test: NORUN = true

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