aboutsummaryrefslogtreecommitdiff
path: root/lib/VMCore
diff options
context:
space:
mode:
Diffstat (limited to 'lib/VMCore')
-rw-r--r--lib/VMCore/Globals.cpp110
-rw-r--r--lib/VMCore/Module.cpp179
2 files changed, 289 insertions, 0 deletions
diff --git a/lib/VMCore/Globals.cpp b/lib/VMCore/Globals.cpp
index c428b889c3..ad7a872b1f 100644
--- a/lib/VMCore/Globals.cpp
+++ b/lib/VMCore/Globals.cpp
@@ -45,6 +45,116 @@ void GlobalValue::destroyConstant() {
llvm_unreachable("You can't GV->destroyConstant()!");
}
+// @LOCALMOD-BEGIN
+
+// Extract the version information from GV.
+static void ExtractVersion(const GlobalValue *GV,
+ StringRef *Name,
+ StringRef *Ver,
+ bool *IsDefault) {
+ // The version information is stored in the GlobalValue's name, e.g.:
+ //
+ // GV Name Name Ver IsDefault
+ // ------------------------------------
+ // foo@@V1 --> foo V1 true
+ // bar@V2 --> bar V2 false
+ // baz --> baz false
+
+ StringRef GVName = GV->getName();
+ size_t atpos = GVName.find("@");
+ if (atpos == StringRef::npos) {
+ *Name = GVName;
+ *Ver = "";
+ *IsDefault = false;
+ return;
+ }
+ *Name = GVName.substr(0, atpos);
+ ++atpos;
+ if (atpos < GVName.size() && GVName[atpos] == '@') {
+ *IsDefault = true;
+ ++atpos;
+ } else {
+ *IsDefault = false;
+ }
+ *Ver = GVName.substr(atpos);
+}
+
+// Set the version information on GV.
+static void SetVersion(Module *M,
+ GlobalValue *GV,
+ StringRef Ver,
+ bool IsDefault) {
+ StringRef Name;
+ StringRef PrevVersion;
+ bool PrevIsDefault;
+ ExtractVersion(GV, &Name, &PrevVersion, &PrevIsDefault);
+
+ // If this symbol already has a version, make sure it matches.
+ if (!PrevVersion.empty()) {
+ if (!PrevVersion.equals(Ver) || PrevIsDefault != IsDefault) {
+ llvm_unreachable("Trying to override symbol version info!");
+ }
+ return;
+ }
+ // If there's no version to set, there's nothing to do.
+ if (Ver.empty())
+ return;
+
+ // Make sure the versioned symbol name doesn't already exist.
+ std::string NewName = Name.str() + (IsDefault ? "@@" : "@") + Ver.str();
+ if (M->getNamedValue(NewName)) {
+ // It may make sense to do this as long as one of the globals being
+ // merged is only a declaration. But since this situation seems to be
+ // a corner case, for now it is unimplemented.
+ llvm_unreachable("Merging unversioned global into "
+ "existing versioned global is unimplemented");
+ }
+ GV->setName(NewName);
+}
+
+StringRef GlobalValue::getUnversionedName() const {
+ StringRef Name;
+ StringRef Ver;
+ bool IsDefaultVersion;
+ ExtractVersion(this, &Name, &Ver, &IsDefaultVersion);
+ return Name;
+}
+
+StringRef GlobalValue::getVersion() const {
+ StringRef Name;
+ StringRef Ver;
+ bool IsDefaultVersion;
+ ExtractVersion(this, &Name, &Ver, &IsDefaultVersion);
+ return Ver;
+}
+
+bool GlobalValue::isDefaultVersion() const {
+ StringRef Name;
+ StringRef Ver;
+ bool IsDefaultVersion;
+ ExtractVersion(this, &Name, &Ver, &IsDefaultVersion);
+ // It is an error to call this function on an unversioned symbol.
+ assert(!Ver.empty());
+ return IsDefaultVersion;
+}
+
+void GlobalValue::setVersionDef(StringRef Version, bool IsDefault) {
+ // This call only makes sense for definitions.
+ assert(!isDeclaration());
+ SetVersion(Parent, this, Version, IsDefault);
+}
+
+void GlobalValue::setNeeded(StringRef Version, StringRef DynFile) {
+ // This call makes sense on declarations or
+ // available-externally definitions.
+ // TODO(pdox): If this is a definition, should we turn it
+ // into a declaration here?
+ assert(isDeclaration() || hasAvailableExternallyLinkage());
+ SetVersion(Parent, this, Version, false);
+ Parent->addNeededRecord(DynFile, this);
+}
+// @LOCALMOD-END
+
/// copyAttributesFrom - copy all additional attributes (those not needed to
/// create a GlobalValue) from the GlobalValue Src to this one.
void GlobalValue::copyAttributesFrom(const GlobalValue *Src) {
diff --git a/lib/VMCore/Module.cpp b/lib/VMCore/Module.cpp
index 5b5176b3c7..a6e335c10c 100644
--- a/lib/VMCore/Module.cpp
+++ b/lib/VMCore/Module.cpp
@@ -22,6 +22,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/LeakDetector.h"
+#include "llvm/Support/ErrorHandling.h" // @LOCALMOD
#include "SymbolTableListTraitsImpl.h"
#include <algorithm>
#include <cstdarg>
@@ -467,3 +468,181 @@ void Module::removeLibrary(StringRef Lib) {
return;
}
}
+
+
+// @LOCALMOD-BEGIN
+// TODO(pdox):
+// If possible, use actual bitcode records instead of NamedMetadata.
+// This is contingent upon whether we can get these changes upstreamed
+// immediately, to avoid creating incompatibilities in the bitcode format.
+
+static std::string
+ModuleMetaGet(const Module *module, StringRef MetaName) {
+ NamedMDNode *node = module->getNamedMetadata(MetaName);
+ if (node == NULL)
+ return "";
+ assert(node->getNumOperands() == 1);
+ MDNode *subnode = node->getOperand(0);
+ assert(subnode->getNumOperands() == 1);
+ MDString *value = dyn_cast<MDString>(subnode->getOperand(0));
+ assert(value != NULL);
+ return value->getString();
+}
+
+static void
+ModuleMetaSet(Module *module, StringRef MetaName, StringRef ValueStr) {
+ NamedMDNode *node = module->getNamedMetadata(MetaName);
+ if (node)
+ module->eraseNamedMetadata(node);
+ node = module->getOrInsertNamedMetadata(MetaName);
+ MDString *value = MDString::get(module->getContext(), ValueStr);
+ node->addOperand(MDNode::get(module->getContext(),
+ makeArrayRef(static_cast<Value*>(value))));
+}
+
+const std::string &Module::getSOName() const {
+ if (ModuleSOName == "")
+ ModuleSOName.assign(ModuleMetaGet(this, "SOName"));
+ return ModuleSOName;
+}
+
+void Module::setSOName(StringRef Name) {
+ ModuleMetaSet(this, "SOName", Name);
+ ModuleSOName = Name;
+}
+
+void Module::setOutputFormat(Module::OutputFormat F) {
+ const char *formatStr;
+ switch (F) {
+ case ObjectOutputFormat: formatStr = "object"; break;
+ case SharedOutputFormat: formatStr = "shared"; break;
+ case ExecutableOutputFormat: formatStr = "executable"; break;
+ default:
+ llvm_unreachable("Unrecognized output format in setOutputFormat()");
+ }
+ ModuleMetaSet(this, "OutputFormat", formatStr);
+}
+
+Module::OutputFormat Module::getOutputFormat() const {
+ std::string formatStr = ModuleMetaGet(this, "OutputFormat");
+ if (formatStr == "" || formatStr == "object")
+ return ObjectOutputFormat;
+ else if (formatStr == "shared")
+ return SharedOutputFormat;
+ else if (formatStr == "executable")
+ return ExecutableOutputFormat;
+ llvm_unreachable("Invalid module compile type in getOutputFormat()");
+}
+
+void
+Module::wrapSymbol(StringRef symName) {
+ std::string wrapSymName("__wrap_");
+ wrapSymName += symName;
+
+ std::string realSymName("__real_");
+ realSymName += symName;
+
+ GlobalValue *SymGV = getNamedValue(symName);
+ GlobalValue *WrapGV = getNamedValue(wrapSymName);
+ GlobalValue *RealGV = getNamedValue(realSymName);
+
+ // Replace uses of "sym" with __wrap_sym.
+ if (SymGV) {
+ if (!WrapGV)
+ WrapGV = cast<GlobalValue>(getOrInsertGlobal(wrapSymName,
+ SymGV->getType()));
+ SymGV->replaceAllUsesWith(ConstantExpr::getBitCast(WrapGV,
+ SymGV->getType()));
+ }
+
+ // Replace uses of "__real_sym" with "sym".
+ if (RealGV) {
+ if (!SymGV)
+ SymGV = cast<GlobalValue>(getOrInsertGlobal(symName, RealGV->getType()));
+ RealGV->replaceAllUsesWith(ConstantExpr::getBitCast(SymGV,
+ RealGV->getType()));
+ }
+}
+
+// The metadata key prefix for NeededRecords.
+static const char *NeededPrefix = "NeededRecord_";
+
+void
+Module::dumpMeta(raw_ostream &OS) const {
+ OS << "OutputFormat: ";
+ switch (getOutputFormat()) {
+ case Module::ObjectOutputFormat: OS << "object"; break;
+ case Module::SharedOutputFormat: OS << "shared"; break;
+ case Module::ExecutableOutputFormat: OS << "executable"; break;
+ }
+ OS << "\n";
+ OS << "SOName: " << getSOName() << "\n";
+ for (Module::lib_iterator L = lib_begin(),
+ E = lib_end();
+ L != E; ++L) {
+ OS << "NeedsLibrary: " << (*L) << "\n";
+ }
+ std::vector<NeededRecord> NList;
+ getNeededRecords(&NList);
+ for (unsigned i = 0; i < NList.size(); ++i) {
+ const NeededRecord &NR = NList[i];
+ OS << StringRef(NeededPrefix) << NR.DynFile << ": ";
+ for (unsigned j = 0; j < NR.Symbols.size(); ++j) {
+ if (j != 0)
+ OS << " ";
+ OS << NR.Symbols[j];
+ }
+ OS << "\n";
+ }
+}
+
+void Module::addNeededRecord(StringRef DynFile, GlobalValue *GV) {
+ if (DynFile.empty()) {
+ // We never resolved this symbol, even after linking.
+ // This should only happen in a shared object.
+ // It is safe to ignore this symbol, and let the dynamic loader
+ // figure out where it comes from.
+ return;
+ }
+ std::string Key = NeededPrefix;
+ Key += DynFile;
+ // Get the node for this file.
+ NamedMDNode *Node = getOrInsertNamedMetadata(Key);
+ // Add this global value's name to the list.
+ MDString *value = MDString::get(getContext(), GV->getName());
+ Node->addOperand(MDNode::get(getContext(),
+ makeArrayRef(static_cast<Value*>(value))));
+}
+
+// Get the NeededRecord for SOName.
+// Returns an empty NeededRecord if there was no metadata found.
+static void getNeededRecordFor(const Module *M,
+ StringRef SOName,
+ Module::NeededRecord *NR) {
+ NR->DynFile = SOName;
+ NR->Symbols.clear();
+
+ std::string Key = NeededPrefix;
+ Key += SOName;
+ NamedMDNode *Node = M->getNamedMetadata(Key);
+ if (!Node)
+ return;
+
+ for (unsigned k = 0; k < Node->getNumOperands(); ++k) {
+ // Insert the symbol name.
+ const MDString *SymName =
+ dyn_cast<MDString>(Node->getOperand(k)->getOperand(0));
+ NR->Symbols.push_back(SymName->getString());
+ }
+}
+
+// Place the complete list of needed records in NeededOut.
+void Module::getNeededRecords(std::vector<NeededRecord> *NeededOut) const {
+ // Iterate through the libraries needed, grabbing each NeededRecord.
+ for (lib_iterator I = lib_begin(), E = lib_end(); I != E; ++I) {
+ NeededRecord NR;
+ getNeededRecordFor(this, *I, &NR);
+ NeededOut->push_back(NR);
+ }
+}
+// @LOCALMOD-END \ No newline at end of file