diff options
author | Alexander Kornienko <alexfh@google.com> | 2013-03-14 10:51:38 +0000 |
---|---|---|
committer | Alexander Kornienko <alexfh@google.com> | 2013-03-14 10:51:38 +0000 |
commit | 647735c781c5b37061ee03d6e9e6c7dda92218e2 (patch) | |
tree | 5a5e56606d41060263048b5a5586b3d2380898ba /lib/Linker/LinkModules.cpp | |
parent | 6aed25d93d1cfcde5809a73ffa7dc1b0d6396f66 (diff) | |
parent | f635ef401786c84df32090251a8cf45981ecca33 (diff) |
Updating branches/google/stable to r176857
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/google/stable@177040 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Linker/LinkModules.cpp')
-rw-r--r-- | lib/Linker/LinkModules.cpp | 286 |
1 files changed, 134 insertions, 152 deletions
diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index fb9eefd568..0acbcfadaf 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -17,16 +17,16 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/Module.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/TypeFinder.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/ValueMapper.h" -#include "llvm/TypeFinder.h" #include <cctype> using namespace llvm; @@ -180,7 +180,7 @@ bool TypeMapTy::areTypesIsomorphic(Type *DstTy, Type *SrcTy) { if (DATy->getNumElements() != cast<ArrayType>(SrcTy)->getNumElements()) return false; } else if (VectorType *DVTy = dyn_cast<VectorType>(DstTy)) { - if (DVTy->getNumElements() != cast<ArrayType>(SrcTy)->getNumElements()) + if (DVTy->getNumElements() != cast<VectorType>(SrcTy)->getNumElements()) return false; } @@ -421,13 +421,6 @@ namespace { } void computeTypeMapping(); - bool categorizeModuleFlagNodes(const NamedMDNode *ModFlags, - DenseMap<MDString*, MDNode*> &ErrorNode, - DenseMap<MDString*, MDNode*> &WarningNode, - DenseMap<MDString*, MDNode*> &OverrideNode, - DenseMap<MDString*, - SmallSetVector<MDNode*, 8> > &RequireNodes, - SmallSetVector<MDString*, 16> &SeenIDs); bool linkAppendingVarProto(GlobalVariable *DstGV, GlobalVariable *SrcGV); bool linkGlobalProto(GlobalVariable *SrcGV); @@ -613,7 +606,8 @@ void ModuleLinker::computeTypeMapping() { // Check to see if there is a dot in the name followed by a digit. size_t DotPos = ST->getName().rfind('.'); if (DotPos == 0 || DotPos == StringRef::npos || - ST->getName().back() == '.' || !isdigit(ST->getName()[DotPos+1])) + ST->getName().back() == '.' || + !isdigit(static_cast<unsigned char>(ST->getName()[DotPos+1]))) continue; // Check to see if the destination module has a struct with the prefix name. @@ -987,76 +981,16 @@ void ModuleLinker::linkNamedMDNodes() { } } -/// categorizeModuleFlagNodes - Categorize the module flags according to their -/// type: Error, Warning, Override, and Require. -bool ModuleLinker:: -categorizeModuleFlagNodes(const NamedMDNode *ModFlags, - DenseMap<MDString*, MDNode*> &ErrorNode, - DenseMap<MDString*, MDNode*> &WarningNode, - DenseMap<MDString*, MDNode*> &OverrideNode, - DenseMap<MDString*, - SmallSetVector<MDNode*, 8> > &RequireNodes, - SmallSetVector<MDString*, 16> &SeenIDs) { - bool HasErr = false; - - for (unsigned I = 0, E = ModFlags->getNumOperands(); I != E; ++I) { - MDNode *Op = ModFlags->getOperand(I); - assert(Op->getNumOperands() == 3 && "Invalid module flag metadata!"); - assert(isa<ConstantInt>(Op->getOperand(0)) && - "Module flag's first operand must be an integer!"); - assert(isa<MDString>(Op->getOperand(1)) && - "Module flag's second operand must be an MDString!"); - - ConstantInt *Behavior = cast<ConstantInt>(Op->getOperand(0)); - MDString *ID = cast<MDString>(Op->getOperand(1)); - Value *Val = Op->getOperand(2); - switch (Behavior->getZExtValue()) { - default: - assert(false && "Invalid behavior in module flag metadata!"); - break; - case Module::Error: { - MDNode *&ErrNode = ErrorNode[ID]; - if (!ErrNode) ErrNode = Op; - if (ErrNode->getOperand(2) != Val) - HasErr = emitError("linking module flags '" + ID->getString() + - "': IDs have conflicting values"); - break; - } - case Module::Warning: { - MDNode *&WarnNode = WarningNode[ID]; - if (!WarnNode) WarnNode = Op; - if (WarnNode->getOperand(2) != Val) - errs() << "WARNING: linking module flags '" << ID->getString() - << "': IDs have conflicting values"; - break; - } - case Module::Require: RequireNodes[ID].insert(Op); break; - case Module::Override: { - MDNode *&OvrNode = OverrideNode[ID]; - if (!OvrNode) OvrNode = Op; - if (OvrNode->getOperand(2) != Val) - HasErr = emitError("linking module flags '" + ID->getString() + - "': IDs have conflicting override values"); - break; - } - } - - SeenIDs.insert(ID); - } - - return HasErr; -} - /// linkModuleFlagsMetadata - Merge the linker flags in Src into the Dest /// module. bool ModuleLinker::linkModuleFlagsMetadata() { + // If the source module has no module flags, we are done. const NamedMDNode *SrcModFlags = SrcM->getModuleFlagsMetadata(); if (!SrcModFlags) return false; - NamedMDNode *DstModFlags = DstM->getOrInsertModuleFlagsMetadata(); - // If the destination module doesn't have module flags yet, then just copy // over the source module's flags. + NamedMDNode *DstModFlags = DstM->getOrInsertModuleFlagsMetadata(); if (DstModFlags->getNumOperands() == 0) { for (unsigned I = 0, E = SrcModFlags->getNumOperands(); I != E; ++I) DstModFlags->addOperand(SrcModFlags->getOperand(I)); @@ -1064,89 +998,137 @@ bool ModuleLinker::linkModuleFlagsMetadata() { return false; } - bool HasErr = false; + // First build a map of the existing module flags and requirements. + DenseMap<MDString*, MDNode*> Flags; + SmallSetVector<MDNode*, 16> Requirements; + for (unsigned I = 0, E = DstModFlags->getNumOperands(); I != E; ++I) { + MDNode *Op = DstModFlags->getOperand(I); + ConstantInt *Behavior = cast<ConstantInt>(Op->getOperand(0)); + MDString *ID = cast<MDString>(Op->getOperand(1)); - // Otherwise, we have to merge them based on their behaviors. First, - // categorize all of the nodes in the modules' module flags. If an error or - // warning occurs, then emit the appropriate message(s). - DenseMap<MDString*, MDNode*> ErrorNode; - DenseMap<MDString*, MDNode*> WarningNode; - DenseMap<MDString*, MDNode*> OverrideNode; - DenseMap<MDString*, SmallSetVector<MDNode*, 8> > RequireNodes; - SmallSetVector<MDString*, 16> SeenIDs; - - HasErr |= categorizeModuleFlagNodes(SrcModFlags, ErrorNode, WarningNode, - OverrideNode, RequireNodes, SeenIDs); - HasErr |= categorizeModuleFlagNodes(DstModFlags, ErrorNode, WarningNode, - OverrideNode, RequireNodes, SeenIDs); - - // Check that there isn't both an error and warning node for a flag. - for (SmallSetVector<MDString*, 16>::iterator - I = SeenIDs.begin(), E = SeenIDs.end(); I != E; ++I) { - MDString *ID = *I; - if (ErrorNode[ID] && WarningNode[ID]) - HasErr = emitError("linking module flags '" + ID->getString() + - "': IDs have conflicting behaviors"); + if (Behavior->getZExtValue() == Module::Require) { + Requirements.insert(cast<MDNode>(Op->getOperand(2))); + } else { + Flags[ID] = Op; + } } - // Early exit if we had an error. - if (HasErr) return true; - - // Get the destination's module flags ready for new operands. - DstModFlags->dropAllReferences(); - - // Add all of the module flags to the destination module. - DenseMap<MDString*, SmallVector<MDNode*, 4> > AddedNodes; - for (SmallSetVector<MDString*, 16>::iterator - I = SeenIDs.begin(), E = SeenIDs.end(); I != E; ++I) { - MDString *ID = *I; - if (OverrideNode[ID]) { - DstModFlags->addOperand(OverrideNode[ID]); - AddedNodes[ID].push_back(OverrideNode[ID]); - } else if (ErrorNode[ID]) { - DstModFlags->addOperand(ErrorNode[ID]); - AddedNodes[ID].push_back(ErrorNode[ID]); - } else if (WarningNode[ID]) { - DstModFlags->addOperand(WarningNode[ID]); - AddedNodes[ID].push_back(WarningNode[ID]); + // Merge in the flags from the source module, and also collect its set of + // requirements. + bool HasErr = false; + for (unsigned I = 0, E = SrcModFlags->getNumOperands(); I != E; ++I) { + MDNode *SrcOp = SrcModFlags->getOperand(I); + ConstantInt *SrcBehavior = cast<ConstantInt>(SrcOp->getOperand(0)); + MDString *ID = cast<MDString>(SrcOp->getOperand(1)); + MDNode *DstOp = Flags.lookup(ID); + unsigned SrcBehaviorValue = SrcBehavior->getZExtValue(); + + // If this is a requirement, add it and continue. + if (SrcBehaviorValue == Module::Require) { + // If the destination module does not already have this requirement, add + // it. + if (Requirements.insert(cast<MDNode>(SrcOp->getOperand(2)))) { + DstModFlags->addOperand(SrcOp); + } + continue; + } + + // If there is no existing flag with this ID, just add it. + if (!DstOp) { + Flags[ID] = SrcOp; + DstModFlags->addOperand(SrcOp); + continue; } - for (SmallSetVector<MDNode*, 8>::iterator - II = RequireNodes[ID].begin(), IE = RequireNodes[ID].end(); - II != IE; ++II) - DstModFlags->addOperand(*II); - } + // Otherwise, perform a merge. + ConstantInt *DstBehavior = cast<ConstantInt>(DstOp->getOperand(0)); + unsigned DstBehaviorValue = DstBehavior->getZExtValue(); + + // If either flag has override behavior, handle it first. + if (DstBehaviorValue == Module::Override) { + // Diagnose inconsistent flags which both have override behavior. + if (SrcBehaviorValue == Module::Override && + SrcOp->getOperand(2) != DstOp->getOperand(2)) { + HasErr |= emitError("linking module flags '" + ID->getString() + + "': IDs have conflicting override values"); + } + continue; + } else if (SrcBehaviorValue == Module::Override) { + // Update the destination flag to that of the source. + DstOp->replaceOperandWith(0, SrcBehavior); + DstOp->replaceOperandWith(2, SrcOp->getOperand(2)); + continue; + } - // Now check that all of the requirements have been satisfied. - for (SmallSetVector<MDString*, 16>::iterator - I = SeenIDs.begin(), E = SeenIDs.end(); I != E; ++I) { - MDString *ID = *I; - SmallSetVector<MDNode*, 8> &Set = RequireNodes[ID]; - - for (SmallSetVector<MDNode*, 8>::iterator - II = Set.begin(), IE = Set.end(); II != IE; ++II) { - MDNode *Node = *II; - assert(isa<MDNode>(Node->getOperand(2)) && - "Module flag's third operand must be an MDNode!"); - MDNode *Val = cast<MDNode>(Node->getOperand(2)); - - MDString *ReqID = cast<MDString>(Val->getOperand(0)); - Value *ReqVal = Val->getOperand(1); - - bool HasValue = false; - for (SmallVectorImpl<MDNode*>::iterator - RI = AddedNodes[ReqID].begin(), RE = AddedNodes[ReqID].end(); - RI != RE; ++RI) { - MDNode *ReqNode = *RI; - if (ReqNode->getOperand(2) == ReqVal) { - HasValue = true; - break; - } + // Diagnose inconsistent merge behavior types. + if (SrcBehaviorValue != DstBehaviorValue) { + HasErr |= emitError("linking module flags '" + ID->getString() + + "': IDs have conflicting behaviors"); + continue; + } + + // Perform the merge for standard behavior types. + switch (SrcBehaviorValue) { + case Module::Require: + case Module::Override: assert(0 && "not possible"); break; + case Module::Error: { + // Emit an error if the values differ. + if (SrcOp->getOperand(2) != DstOp->getOperand(2)) { + HasErr |= emitError("linking module flags '" + ID->getString() + + "': IDs have conflicting values"); } + continue; + } + case Module::Warning: { + // Emit a warning if the values differ. + if (SrcOp->getOperand(2) != DstOp->getOperand(2)) { + errs() << "WARNING: linking module flags '" << ID->getString() + << "': IDs have conflicting values"; + } + continue; + } + case Module::Append: { + MDNode *DstValue = cast<MDNode>(DstOp->getOperand(2)); + MDNode *SrcValue = cast<MDNode>(SrcOp->getOperand(2)); + unsigned NumOps = DstValue->getNumOperands() + SrcValue->getNumOperands(); + Value **VP, **Values = VP = new Value*[NumOps]; + for (unsigned i = 0, e = DstValue->getNumOperands(); i != e; ++i, ++VP) + *VP = DstValue->getOperand(i); + for (unsigned i = 0, e = SrcValue->getNumOperands(); i != e; ++i, ++VP) + *VP = SrcValue->getOperand(i); + DstOp->replaceOperandWith(2, MDNode::get(DstM->getContext(), + ArrayRef<Value*>(Values, + NumOps))); + delete[] Values; + break; + } + case Module::AppendUnique: { + SmallSetVector<Value*, 16> Elts; + MDNode *DstValue = cast<MDNode>(DstOp->getOperand(2)); + MDNode *SrcValue = cast<MDNode>(SrcOp->getOperand(2)); + for (unsigned i = 0, e = DstValue->getNumOperands(); i != e; ++i) + Elts.insert(DstValue->getOperand(i)); + for (unsigned i = 0, e = SrcValue->getNumOperands(); i != e; ++i) + Elts.insert(SrcValue->getOperand(i)); + DstOp->replaceOperandWith(2, MDNode::get(DstM->getContext(), + ArrayRef<Value*>(Elts.begin(), + Elts.end()))); + break; + } + } + } - if (!HasValue) - HasErr = emitError("linking module flags '" + ReqID->getString() + - "': does not have the required value"); + // Check all of the requirements. + for (unsigned I = 0, E = Requirements.size(); I != E; ++I) { + MDNode *Requirement = Requirements[I]; + MDString *Flag = cast<MDString>(Requirement->getOperand(0)); + Value *ReqValue = Requirement->getOperand(1); + + MDNode *Op = Flags[Flag]; + if (!Op || Op->getOperand(2) != ReqValue) { + HasErr |= emitError("linking module flags '" + Flag->getString() + + "': does not have the required value"); + continue; } } @@ -1310,7 +1292,7 @@ bool ModuleLinker::run() { //===----------------------------------------------------------------------===// /// LinkModules - This function links two modules together, with the resulting -/// left module modified to be the composite of the two input modules. If an +/// Dest module modified to be the composite of the two input modules. If an /// error occurs, true is returned and ErrorMsg (if not null) is set to indicate /// the problem. Upon failure, the Dest module could be in a modified state, /// and shouldn't be relied on to be consistent. |