Index: lld/trunk/ELF/Relocations.h =================================================================== --- lld/trunk/ELF/Relocations.h +++ lld/trunk/ELF/Relocations.h @@ -73,6 +73,35 @@ R_TLSLD_PC, }; +// Build a bitmask with one bit set for each RelExpr. +// +// Constexpr function arguments can't be used in static asserts, so we +// use template arguments to build the mask. +// But function template partial specializations don't exist (needed +// for base case of the recursion), so we need a dummy struct. +template struct RelExprMaskBuilder { + static inline uint64_t build() { return 0; } +}; + +// Specialization for recursive case. +template +struct RelExprMaskBuilder { + static inline uint64_t build() { + static_assert(0 <= Head && Head < 64, + "RelExpr is too large for 64-bit mask!"); + return (uint64_t(1) << Head) | RelExprMaskBuilder::build(); + } +}; + +// Return true if `Expr` is one of `Exprs`. +// There are fewer than 64 RelExpr's, so we can represent any set of +// RelExpr's as a constant bit mask and test for membership with a +// couple cheap bitwise operations. +template bool isRelExprOneOf(RelExpr Expr) { + assert(0 <= Expr && Expr < 64 && "RelExpr is too large for 64-bit mask!"); + return (uint64_t(1) << Expr) & RelExprMaskBuilder::build(); +} + // Architecture-neutral representation of relocation. struct Relocation { RelExpr Expr; Index: lld/trunk/ELF/Relocations.cpp =================================================================== --- lld/trunk/ELF/Relocations.cpp +++ lld/trunk/ELF/Relocations.cpp @@ -62,12 +62,10 @@ namespace elf { static bool refersToGotEntry(RelExpr Expr) { - return Expr == R_GOT || Expr == R_GOT_OFF || Expr == R_MIPS_GOT_LOCAL_PAGE || - Expr == R_MIPS_GOT_OFF || Expr == R_MIPS_GOT_OFF32 || - Expr == R_MIPS_TLSGD || Expr == R_MIPS_TLSLD || - Expr == R_GOT_PAGE_PC || Expr == R_GOT_PC || Expr == R_GOT_FROM_END || - Expr == R_TLSGD || Expr == R_TLSGD_PC || Expr == R_TLSDESC || - Expr == R_TLSDESC_PAGE; + return isRelExprOneOf(Expr); } static bool isPreemptible(const SymbolBody &Body, uint32_t Type) { @@ -302,16 +300,16 @@ } static bool needsPlt(RelExpr Expr) { - return Expr == R_PLT_PC || Expr == R_PPC_PLT_OPD || Expr == R_PLT || - Expr == R_PLT_PAGE_PC || Expr == R_THUNK_PLT_PC; + return isRelExprOneOf(Expr); } // True if this expression is of the form Sym - X, where X is a position in the // file (PC, or GOT for example). static bool isRelExpr(RelExpr Expr) { - return Expr == R_PC || Expr == R_GOTREL || Expr == R_GOTREL_FROM_END || - Expr == R_MIPS_GOTREL || Expr == R_PAGE_PC || Expr == R_RELAX_GOT_PC || - Expr == R_THUNK_PC || Expr == R_THUNK_PLT_PC; + return isRelExprOneOf( + Expr); } template @@ -320,12 +318,11 @@ InputSectionBase &S, typename ELFT::uint RelOff) { // These expressions always compute a constant - if (E == R_SIZE || E == R_GOT_FROM_END || E == R_GOT_OFF || - E == R_MIPS_GOT_LOCAL_PAGE || E == R_MIPS_GOT_OFF || - E == R_MIPS_GOT_OFF32 || E == R_MIPS_TLSGD || E == R_GOT_PAGE_PC || - E == R_GOT_PC || E == R_PLT_PC || E == R_TLSGD_PC || E == R_TLSGD || - E == R_PPC_PLT_OPD || E == R_TLSDESC_CALL || E == R_TLSDESC_PAGE || - E == R_HINT || E == R_THUNK_PC || E == R_THUNK_PLT_PC) + if (isRelExprOneOf(E)) return true; // These never do, except if the entire file is position dependent or if @@ -659,12 +656,12 @@ // Ignore "hint" and TLS Descriptor call relocation because they are // only markers for relaxation. - if (Expr == R_HINT || Expr == R_TLSDESC_CALL) + if (isRelExprOneOf(Expr)) continue; - if (needsPlt(Expr) || Expr == R_THUNK_ABS || Expr == R_THUNK_PC || - Expr == R_THUNK_PLT_PC || refersToGotEntry(Expr) || - !isPreemptible(Body, Type)) { + if (needsPlt(Expr) || + isRelExprOneOf(Expr) || + refersToGotEntry(Expr) || !isPreemptible(Body, Type)) { // If the relocation points to something in the file, we can process it. bool Constant = isStaticLinkTimeConstant(Expr, Type, Body, C, RI.r_offset);