int decl_interposable(decl *d) { /* * Match gcc's -fsemantic-interposition default, where: * * -fpic -fpie -fsemantic-interposition function-visibility | can-inline-non-static function? * 0 0 0 default yes (-fno-pic) * 0 0 1 default yes (-fno-pic) * 0 1 0 default yes (-fno-pic) * 0 1 1 default yes (-fno-pic) * 0 0 0 protected/hidden yes (-fno-pic) * 0 0 1 protected/hidden yes (-fno-pic) * 0 1 0 protected/hidden yes (-fno-pic) * 0 1 1 protected/hidden yes (-fno-pic) * * 1 1 1 protected/hidden yes (-fvisibility=protected/hidden) * 1 1 0 protected/hidden yes (-fvisibility=protected/hidden) * 1 0 1 protected/hidden yes (-fvisibility=protected/hidden) * 1 0 0 protected/hidden yes (-fvisibility=protected/hidden) * * 1 1 1 default yes (-fpie) * 1 1 0 default yes (-fpie) * 1 0 1 default no * 1 0 0 default yes (-fno-semantic-interposition) * * -fno-pic: -fsemantic-interposition and -fvisibility=... have no effect * * -fpic: We can inline non-static, default-visibility functions when * -fno-semantic-interposition is set otherwise, the ELF abi says a * non-static default-visibility function may be overridden. */ if(!cc1_fopt.pic && !cc1_fopt.pie) return 0; /* not compiling for interposable shared library */ if(cc1_fopt.pie && decl_defined(d, 0)) return 0; /* pie, this is the main program, can't have its symbols interposed */ switch(decl_linkage(d)){ case linkage_internal: case linkage_none: return 0; /* static decl, fixed */ case linkage_external: break; } switch(decl_visibility(d)){ case VISIBILITY_DEFAULT: break; case VISIBILITY_PROTECTED: return 0; /* symbol visible, but not interposable by contract */ case VISIBILITY_HIDDEN: return 0; /* symbol not visible, so not interposable */ } /* extern decls (that aren't explicitly visibility-attributed) are interposable */ if(!decl_defined(d, 0)) return 1; return cc1_fopt.semantic_interposition; }
int decl_needs_GOTPLT(decl *d) { /* need to differentiate: * extern int x; // always pic (aka x@GOTPCREL(%rip)) * * __attribute__((visibility("hidden/protected"))) * extern int x; // pic but we can avoid the GOT, e.g. x(%rip) * * int x = 3; // pic, must go via GOT * * -fno-semantic-interposition / -fpie * int x = 3; // pic, can avoid the GOT because it's effectively hidden/protected * * -fno-semantic-interposition / -fno-pie (but -fpic) * extern int x; // pic, must use GOT as we don't know if it's in our module */ if(!cc1_fopt.pic && !cc1_fopt.pie) return 0; if(decl_linkage(d) == linkage_internal) return 0; if(cc1_fopt.pie){ /* gcc acts as if variables are always local/accessible without the GOT in pie-code */ int is_var = 0; /* !type_is(d->ref, type_func) */ if((is_var || decl_defined(d, 0)) && !attribute_present(d, attr_weak)) return 0; } switch(decl_visibility(d)){ case VISIBILITY_DEFAULT: break; case VISIBILITY_HIDDEN: case VISIBILITY_PROTECTED: return 0; } return 1; }
void asm_declare_decl_init(decl *d) { enum section_type sec; if((d->store & STORE_MASK_STORE) == store_extern){ asm_predeclare_extern(d); return; } sec = type_is_const(d->ref) ? SECTION_RODATA : SECTION_DATA; if(d->bits.var.init.dinit && !decl_init_is_zero(d->bits.var.init.dinit)){ asm_nam_begin(sec, d); asm_declare_init(sec, d->bits.var.init.dinit, d->ref); asm_out_section(sec, "\n"); }else if(d->bits.var.init.compiler_generated && fopt_mode & FOPT_COMMON){ const char *common_prefix = "comm "; /* section doesn't matter */ sec = SECTION_BSS; if(decl_linkage(d) == linkage_internal){ if(AS_SUPPORTS_LOCAL_COMMON){ asm_out_section(sec, ".local %s\n", decl_asm_spel(d)); }else{ common_prefix = "zerofill __DATA,__bss,"; } } asm_out_section(sec, ".%s%s,%u,%u\n", common_prefix, decl_asm_spel(d), decl_size(d), decl_align(d)); }else{ /* always resB, since we use decl_size() */ asm_nam_begin(SECTION_BSS, d); asm_reserve_bytes(SECTION_BSS, decl_size(d)); } }
int decl_unused_and_internal(decl *d) { /* need to check every clone of the decl */ decl *i; int used = 0; for(i = d; i; i = i->proto){ if(i->flags & DECL_FLAGS_USED){ used = 1; goto fin; } } for(i = d; i; i = i->impl){ if(i->flags & DECL_FLAGS_USED){ used = 1; goto fin; } } fin: return !used && decl_linkage(d) != linkage_external; }