Skip to content

Commit 45477ad

Browse files
authored
RuntimeLibcalls: Add methods to recognize libcall names (#149001)
Also replace the current static DenseMap of preserved symbol names in the Symtab hack with this. That was broken statefulness across compiles, so this at least fixes that. However this is still broken, llvm-as shouldn't really depend on the triple.
1 parent cf36f49 commit 45477ad

File tree

5 files changed

+100
-24
lines changed

5 files changed

+100
-24
lines changed

llvm/include/llvm/ADT/StringTable.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ class StringTable {
118118
constexpr Iterator(const Iterator &RHS) = default;
119119
constexpr Iterator(Iterator &&RHS) = default;
120120

121+
Iterator &operator=(const Iterator &RHS) {
122+
Table = RHS.Table;
123+
O = RHS.O;
124+
S = RHS.S;
125+
return *this;
126+
}
127+
121128
bool operator==(const Iterator &RHS) const {
122129
assert(Table == RHS.Table && "Compared iterators for unrelated tables!");
123130
return O == RHS.O;
@@ -132,6 +139,8 @@ class StringTable {
132139
O = O.value() + (*Table)[O].size() + 1;
133140
return *this;
134141
}
142+
143+
Offset offset() const { return O; }
135144
};
136145

137146
constexpr Iterator begin() const { return Iterator(*this, 0); }

llvm/include/llvm/IR/RuntimeLibcalls.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ struct RuntimeLibcallsInfo {
132132
return ImplToLibcall[Impl];
133133
}
134134

135+
/// Check if this is valid libcall for the current module, otherwise
136+
/// RTLIB::Unsupported.
137+
RTLIB::LibcallImpl getSupportedLibcallImpl(StringRef FuncName) const;
138+
135139
private:
136140
static const RTLIB::LibcallImpl
137141
DefaultLibcallImpls[RTLIB::UNKNOWN_LIBCALL + 1];
@@ -156,6 +160,14 @@ struct RuntimeLibcallsInfo {
156160
/// Map from a concrete LibcallImpl implementation to its RTLIB::Libcall kind.
157161
LLVM_ABI static const RTLIB::Libcall ImplToLibcall[RTLIB::NumLibcallImpls];
158162

163+
/// Check if a function name is a recognized runtime call of any kind. This
164+
/// does not consider if this call is available for any current compilation,
165+
/// just that it is a known call somewhere. This returns the set of all
166+
/// LibcallImpls which match the name; multiple implementations with the same
167+
/// name may exist but differ in interpretation based on the target context.
168+
LLVM_ABI static iterator_range<ArrayRef<uint16_t>::const_iterator>
169+
getRecognizedLibcallImpls(StringRef FuncName);
170+
159171
static bool darwinHasSinCosStret(const Triple &TT) {
160172
if (!TT.isOSDarwin())
161173
return false;

llvm/lib/IR/RuntimeLibcalls.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,51 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
135135
}
136136
}
137137

138+
RTLIB::LibcallImpl
139+
RuntimeLibcallsInfo::getSupportedLibcallImpl(StringRef FuncName) const {
140+
const ArrayRef<uint16_t> RuntimeLibcallNameOffsets(
141+
RuntimeLibcallNameOffsetTable);
142+
143+
iterator_range<ArrayRef<uint16_t>::const_iterator> Range =
144+
getRecognizedLibcallImpls(FuncName);
145+
146+
for (auto I = Range.begin(); I != Range.end(); ++I) {
147+
RTLIB::LibcallImpl Impl =
148+
static_cast<RTLIB::LibcallImpl>(I - RuntimeLibcallNameOffsets.begin());
149+
150+
// FIXME: This should not depend on looking up ImplToLibcall, only the list
151+
// of libcalls for the module.
152+
RTLIB::LibcallImpl Recognized = LibcallImpls[ImplToLibcall[Impl]];
153+
if (Recognized != RTLIB::Unsupported)
154+
return Recognized;
155+
}
156+
157+
return RTLIB::Unsupported;
158+
}
159+
160+
iterator_range<ArrayRef<uint16_t>::const_iterator>
161+
RuntimeLibcallsInfo::getRecognizedLibcallImpls(StringRef FuncName) {
162+
StringTable::Iterator It = lower_bound(RuntimeLibcallImplNameTable, FuncName);
163+
if (It == RuntimeLibcallImplNameTable.end() || *It != FuncName)
164+
return iterator_range(ArrayRef<uint16_t>());
165+
166+
uint16_t IndexVal = It.offset().value();
167+
const ArrayRef<uint16_t> TableRef(RuntimeLibcallNameOffsetTable);
168+
169+
ArrayRef<uint16_t>::const_iterator E = TableRef.end();
170+
ArrayRef<uint16_t>::const_iterator EntriesBegin =
171+
std::lower_bound(TableRef.begin(), E, IndexVal);
172+
ArrayRef<uint16_t>::const_iterator EntriesEnd = EntriesBegin;
173+
174+
while (EntriesEnd != E && *EntriesEnd == IndexVal)
175+
++EntriesEnd;
176+
177+
assert(EntriesBegin != E &&
178+
"libcall found in name table but not offset table");
179+
180+
return make_range(EntriesBegin, EntriesEnd);
181+
}
182+
138183
bool RuntimeLibcallsInfo::darwinHasExp10(const Triple &TT) {
139184
switch (TT.getOS()) {
140185
case Triple::MacOSX:

llvm/lib/Object/IRSymtab.cpp

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ static const char *PreservedSymbols[] = {
5454
"__stack_chk_guard",
5555
};
5656

57+
static bool isPreservedGlobalVarName(StringRef Name) {
58+
return StringRef(PreservedSymbols[0]) == Name ||
59+
StringRef(PreservedSymbols[1]) == Name;
60+
}
61+
5762
namespace {
5863

5964
const char *getExpectedProducerName() {
@@ -81,12 +86,16 @@ struct Builder {
8186
// The StringTableBuilder does not create a copy of any strings added to it,
8287
// so this provides somewhere to store any strings that we create.
8388
Builder(SmallVector<char, 0> &Symtab, StringTableBuilder &StrtabBuilder,
84-
BumpPtrAllocator &Alloc)
85-
: Symtab(Symtab), StrtabBuilder(StrtabBuilder), Saver(Alloc) {}
89+
BumpPtrAllocator &Alloc, const Triple &TT)
90+
: Symtab(Symtab), StrtabBuilder(StrtabBuilder), Saver(Alloc), TT(TT),
91+
Libcalls(TT) {}
8692

8793
DenseMap<const Comdat *, int> ComdatMap;
8894
Mangler Mang;
89-
Triple TT;
95+
const Triple &TT;
96+
97+
// FIXME: This shouldn't be here.
98+
RTLIB::RuntimeLibcallsInfo Libcalls;
9099

91100
std::vector<storage::Comdat> Comdats;
92101
std::vector<storage::Module> Mods;
@@ -98,6 +107,10 @@ struct Builder {
98107

99108
std::vector<storage::Str> DependentLibraries;
100109

110+
bool isPreservedLibFuncName(StringRef Name) {
111+
return Libcalls.getSupportedLibcallImpl(Name) != RTLIB::Unsupported;
112+
}
113+
101114
void setStr(storage::Str &S, StringRef Value) {
102115
S.Offset = StrtabBuilder.add(Value);
103116
S.Size = Value.size();
@@ -213,18 +226,6 @@ Expected<int> Builder::getComdatIndex(const Comdat *C, const Module *M) {
213226
return P.first->second;
214227
}
215228

216-
static DenseSet<StringRef> buildPreservedSymbolsSet(const Triple &TT) {
217-
DenseSet<StringRef> PreservedSymbolSet(std::begin(PreservedSymbols),
218-
std::end(PreservedSymbols));
219-
// FIXME: Do we need to pass in ABI fields from TargetOptions?
220-
RTLIB::RuntimeLibcallsInfo Libcalls(TT);
221-
for (RTLIB::LibcallImpl Impl : Libcalls.getLibcallImpls()) {
222-
if (Impl != RTLIB::Unsupported)
223-
PreservedSymbolSet.insert(Libcalls.getLibcallImplName(Impl));
224-
}
225-
return PreservedSymbolSet;
226-
}
227-
228229
Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
229230
const SmallPtrSet<GlobalValue *, 4> &Used,
230231
ModuleSymbolTable::Symbol Msym) {
@@ -278,13 +279,11 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
278279
return Error::success();
279280
}
280281

281-
setStr(Sym.IRName, GV->getName());
282-
283-
static const DenseSet<StringRef> PreservedSymbolsSet =
284-
buildPreservedSymbolsSet(GV->getParent()->getTargetTriple());
285-
bool IsPreservedSymbol = PreservedSymbolsSet.contains(GV->getName());
282+
StringRef GVName = GV->getName();
283+
setStr(Sym.IRName, GVName);
286284

287-
if (Used.count(GV) || IsPreservedSymbol)
285+
if (Used.count(GV) || isPreservedLibFuncName(GVName) ||
286+
isPreservedGlobalVarName(GVName))
288287
Sym.Flags |= 1 << storage::Symbol::FB_used;
289288
if (GV->isThreadLocal())
290289
Sym.Flags |= 1 << storage::Symbol::FB_tls;
@@ -351,7 +350,6 @@ Error Builder::build(ArrayRef<Module *> IRMods) {
351350
setStr(Hdr.Producer, kExpectedProducerName);
352351
setStr(Hdr.TargetTriple, IRMods[0]->getTargetTriple().str());
353352
setStr(Hdr.SourceFileName, IRMods[0]->getSourceFileName());
354-
TT = IRMods[0]->getTargetTriple();
355353

356354
for (auto *M : IRMods)
357355
if (Error Err = addModule(M))
@@ -377,7 +375,8 @@ Error Builder::build(ArrayRef<Module *> IRMods) {
377375
Error irsymtab::build(ArrayRef<Module *> Mods, SmallVector<char, 0> &Symtab,
378376
StringTableBuilder &StrtabBuilder,
379377
BumpPtrAllocator &Alloc) {
380-
return Builder(Symtab, StrtabBuilder, Alloc).build(Mods);
378+
const Triple &TT = Mods[0]->getTargetTriple();
379+
return Builder(Symtab, StrtabBuilder, Alloc, TT).build(Mods);
381380
}
382381

383382
// Upgrade a vector of bitcode modules created by an old version of LLVM by

llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,19 @@ class RuntimeLibcallEmitter {
236236
for (RuntimeLibcall &LibCall : RuntimeLibcallDefList)
237237
Def2RuntimeLibcall[LibCall.getDef()] = &LibCall;
238238

239-
ArrayRef<const Record *> AllRuntimeLibcallImpls =
239+
ArrayRef<const Record *> AllRuntimeLibcallImplsRaw =
240240
Records.getAllDerivedDefinitions("RuntimeLibcallImpl");
241+
242+
SmallVector<const Record *, 1024> AllRuntimeLibcallImpls(
243+
AllRuntimeLibcallImplsRaw);
244+
245+
// Sort by libcall impl name, not the enum name. This keeps the order
246+
// suitable for using the name table for libcall recognition binary search.
247+
llvm::sort(AllRuntimeLibcallImpls, [](const Record *A, const Record *B) {
248+
return A->getValueAsString("LibCallFuncName") <
249+
B->getValueAsString("LibCallFuncName");
250+
});
251+
241252
RuntimeLibcallImplDefList.reserve(AllRuntimeLibcallImpls.size());
242253

243254
size_t LibCallImplEnumVal = 1;

0 commit comments

Comments
 (0)