* bit 2 : HasPrologueData
* bit 3 : HasPersonalityFn
* bits 4-13 : CallingConvention
- * bits 14-15 : [reserved]
+ * bits 14 : HasGC
+ * bits 15 : [reserved]
*/
/// Bits from GlobalObject::GlobalObjectSubclassData.
/// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm
/// to use during code generation.
- bool hasGC() const;
- const char *getGC() const;
- void setGC(const char *Str);
+ bool hasGC() const {
+ return getSubclassDataFromValue() & (1<<14);
+ }
+ const std::string &getGC() const;
+ void setGC(const std::string Str);
void clearGC();
/// @brief adds the attribute to the list of attributes.
/// tag registered with an LLVMContext has an unique ID.
uint32_t getOperandBundleTagID(StringRef Tag) const;
+
+ /// Define the GC for a function
+ void setGC(const Function &Fn, std::string GCName);
+
+ /// Return the GC for a function
+ const std::string &getGC(const Function &Fn);
+
+ /// Remove the GC for a function
+ void deleteGC(const Function &Fn);
+
+
typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context,
unsigned LocCookie);
const char *LLVMGetGC(LLVMValueRef Fn) {
Function *F = unwrap<Function>(Fn);
- return F->hasGC()? F->getGC() : nullptr;
+ return F->hasGC()? F->getGC().c_str() : nullptr;
}
void LLVMSetGC(LLVMValueRef Fn, const char *GC) {
setAttributes(PAL);
}
-// Maintain the GC name for each function in an on-the-side table. This saves
-// allocating an additional word in Function for programs which do not use GC
-// (i.e., most programs) at the cost of increased overhead for clients which do
-// use GC.
-static DenseMap<const Function*,PooledStringPtr> *GCNames;
-static StringPool *GCNamePool;
-static ManagedStatic<sys::SmartRWMutex<true> > GCLock;
-
-bool Function::hasGC() const {
- sys::SmartScopedReader<true> Reader(*GCLock);
- return GCNames && GCNames->count(this);
-}
-
-const char *Function::getGC() const {
+const std::string &Function::getGC() const {
assert(hasGC() && "Function has no collector");
- sys::SmartScopedReader<true> Reader(*GCLock);
- return *(*GCNames)[this];
+ return getContext().getGC(*this);
}
-void Function::setGC(const char *Str) {
- sys::SmartScopedWriter<true> Writer(*GCLock);
- if (!GCNamePool)
- GCNamePool = new StringPool();
- if (!GCNames)
- GCNames = new DenseMap<const Function*,PooledStringPtr>();
- (*GCNames)[this] = GCNamePool->intern(Str);
+void Function::setGC(const std::string Str) {
+ setValueSubclassDataBit(14, !Str.empty());
+ getContext().setGC(*this, std::move(Str));
}
void Function::clearGC() {
- sys::SmartScopedWriter<true> Writer(*GCLock);
- if (GCNames) {
- GCNames->erase(this);
- if (GCNames->empty()) {
- delete GCNames;
- GCNames = nullptr;
- if (GCNamePool->empty()) {
- delete GCNamePool;
- GCNamePool = nullptr;
- }
- }
- }
+ if (!hasGC())
+ return;
+ getContext().deleteGC(*this);
+ setValueSubclassDataBit(14, false);
}
/// Copy all additional attributes (those not needed to create a Function) from
uint32_t LLVMContext::getOperandBundleTagID(StringRef Tag) const {
return pImpl->getOperandBundleTagID(Tag);
}
+
+void LLVMContext::setGC(const Function &Fn, std::string GCName) {
+ auto It = pImpl->GCNames.find(&Fn);
+
+ if (It == pImpl->GCNames.end()) {
+ pImpl->GCNames.insert(std::make_pair(&Fn, std::move(GCName)));
+ return;
+ }
+ It->second = std::move(GCName);
+}
+const std::string &LLVMContext::getGC(const Function &Fn) {
+ return pImpl->GCNames[&Fn];
+}
+void LLVMContext::deleteGC(const Function &Fn) {
+ pImpl->GCNames.erase(&Fn);
+}
void getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const;
uint32_t getOperandBundleTagID(StringRef Tag) const;
+ /// Maintain the GC name for each function.
+ ///
+ /// This saves allocating an additional word in Function for programs which
+ /// do not use GC (i.e., most programs) at the cost of increased overhead for
+ /// clients which do use GC.
+ DenseMap<const Function*, std::string> GCNames;
+
LLVMContextImpl(LLVMContext &C);
~LLVMContextImpl();
static bool shouldRewriteFunction(Function &F) {
// TODO: This should check the GCStrategy
if (F.hasGC()) {
- const char *FunctionGCName = F.getGC();
+ const auto &FunctionGCName = F.getGC();
const StringRef StatepointExampleName("statepoint-example");
const StringRef CoreCLRName("coreclr");
return (StatepointExampleName == FunctionGCName) ||
static bool shouldRewriteStatepointsIn(Function &F) {
// TODO: This should check the GCStrategy
if (F.hasGC()) {
- const char *FunctionGCName = F.getGC();
+ const auto &FunctionGCName = F.getGC();
const StringRef StatepointExampleName("statepoint-example");
const StringRef CoreCLRName("coreclr");
return (StatepointExampleName == FunctionGCName) ||