diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -124,36 +124,27 @@ Twine(llvm::maxIntN(n)) + "]" + hint); } -namespace { -// 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; } -}; +// Build a bitmask with one bit set for each 64 subset of RelExpr. +static constexpr uint64_t buildMask() { 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(); - } -}; -} // namespace +template +static constexpr uint64_t buildMask(int head, Tails... tails) { + return (0 <= head && head < 64 ? uint64_t(1) << head : 0) | + buildMask(tails...); +} // 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 oneof(RelExpr expr) { - assert(0 <= expr && (int)expr < 64 && - "RelExpr is too large for 64-bit mask!"); - return (uint64_t(1) << expr) & RelExprMaskBuilder::build(); +// There are more than 64 but less than 128 RelExprs, so we divide the set of +// exprs into [0, 64) and [64, 128) and represent each range as a constant +// 64-bit mask. Then we decide which mask to test depending on the value of +// expr and use a simple shift and bitwise-and to test for membership. +template static bool oneof(RelExpr expr) { + assert(0 <= expr && (int)expr < 128 && + "RelExpr is too large for 128-bit mask!"); + + if (expr >= 64) + return (uint64_t(1) << (expr - 64)) & buildMask((Exprs - 64)...); + return (uint64_t(1) << expr) & buildMask(Exprs...); } static RelType getMipsPairType(RelType type, bool isLocal) {