diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Linker/LinkModules.cpp | 191 | ||||
| -rw-r--r-- | llvm/lib/VMCore/Module.cpp | 40 | 
2 files changed, 226 insertions, 5 deletions
diff --git a/llvm/lib/Linker/LinkModules.cpp b/llvm/lib/Linker/LinkModules.cpp index 73ae6ad8c2d..8e2fc4fe3fd 100644 --- a/llvm/lib/Linker/LinkModules.cpp +++ b/llvm/lib/Linker/LinkModules.cpp @@ -16,8 +16,10 @@  #include "llvm/DerivedTypes.h"  #include "llvm/Instructions.h"  #include "llvm/Module.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/DenseSet.h"  #include "llvm/ADT/Optional.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h"  #include "llvm/Support/raw_ostream.h"  #include "llvm/Support/Path.h"  #include "llvm/Transforms/Utils/Cloning.h" @@ -406,11 +408,19 @@ 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);      bool linkFunctionProto(Function *SrcF);      bool linkAliasProto(GlobalAlias *SrcA); +    bool linkModuleFlagsMetadata();      void linkAppendingVarInit(const AppendingVarInfo &AVI);      void linkGlobalInits(); @@ -938,8 +948,11 @@ void ModuleLinker::linkAliasBodies() {  /// linkNamedMDNodes - Insert all of the named mdnodes in Src into the Dest  /// module.  void ModuleLinker::linkNamedMDNodes() { +  const NamedMDNode *SrcModFlags = SrcM->getModuleFlagsMetadata();    for (Module::const_named_metadata_iterator I = SrcM->named_metadata_begin(),         E = SrcM->named_metadata_end(); I != E; ++I) { +    // Don't link module flags here. Do them separately. +    if (&*I == SrcModFlags) continue;      NamedMDNode *DestNMD = DstM->getOrInsertNamedMetadata(I->getName());      // Add Src elements into Dest node.      for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) @@ -947,10 +960,175 @@ void ModuleLinker::linkNamedMDNodes() {                                     RF_None, &TypeMap));    }  } + +/// categorizeModuleFlagNodes - +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() { +  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. +  if (DstModFlags->getNumOperands() == 0) { +    for (unsigned I = 0, E = SrcModFlags->getNumOperands(); I != E; ++I) +      DstModFlags->addOperand(SrcModFlags->getOperand(I)); + +    return false; +  } + +  bool HasErr = false; + +  // 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"); +  } + +  // 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]); +    } + +    for (SmallSetVector<MDNode*, 8>::iterator +           II = RequireNodes[ID].begin(), IE = RequireNodes[ID].end(); +         II != IE; ++II) +      DstModFlags->addOperand(*II); +  } + +  // 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; +        } +      } + +      if (!HasValue) +        HasErr = emitError("Linking module flags '" + ReqID->getString() + +                           "': does not have the required value!"); +    } +  } + +  return HasErr; +}  bool ModuleLinker::run() { -  assert(DstM && "Null Destination module"); -  assert(SrcM && "Null Source Module"); +  assert(DstM && "Null destination module"); +  assert(SrcM && "Null source module");    // Inherit the target data from the source module if the destination module    // doesn't have one already. @@ -1030,7 +1208,6 @@ bool ModuleLinker::run() {    // Link in the function bodies that are defined in the source module into    // DstM.    for (Module::iterator SF = SrcM->begin(), E = SrcM->end(); SF != E; ++SF) { -          // Skip if not linking from source.      if (DoNotLinkFromSource.count(SF)) continue; @@ -1048,11 +1225,15 @@ bool ModuleLinker::run() {    // Resolve all uses of aliases with aliasees.    linkAliasBodies(); -  // Remap all of the named mdnoes in Src into the DstM module. We do this +  // Remap all of the named MDNodes in Src into the DstM module. We do this    // after linking GlobalValues so that MDNodes that reference GlobalValues    // are properly remapped.    linkNamedMDNodes(); +  // Merge the module flags into the DstM module. +  if (linkModuleFlagsMetadata()) +    return true; +    // Process vector of lazily linked in functions.    bool LinkedInAnyFunctions;    do { diff --git a/llvm/lib/VMCore/Module.cpp b/llvm/lib/VMCore/Module.cpp index c29029bf6c0..09468184cc1 100644 --- a/llvm/lib/VMCore/Module.cpp +++ b/llvm/lib/VMCore/Module.cpp @@ -321,11 +321,51 @@ NamedMDNode *Module::getOrInsertNamedMetadata(StringRef Name) {    return NMD;  } +/// eraseNamedMetadata - Remove the given NamedMDNode from this module and +/// delete it.  void Module::eraseNamedMetadata(NamedMDNode *NMD) {    static_cast<StringMap<NamedMDNode *> *>(NamedMDSymTab)->erase(NMD->getName());    NamedMDList.erase(NMD);  } +/// getModuleFlagsMetadata - Returns the NamedMDNode in the module that +/// represents module-level flags. This method returns null if there are no +/// module-level flags. +NamedMDNode *Module::getModuleFlagsMetadata() const { +  return getNamedMetadata("llvm.module.flags"); +} + +/// getOrInsertModuleFlagsMetadata - Returns the NamedMDNode in the module that +/// represents module-level flags. If module-level flags aren't found, it +/// creates the named metadata that contains them. +NamedMDNode *Module::getOrInsertModuleFlagsMetadata() { +  return getOrInsertNamedMetadata("llvm.module.flags"); +} + +/// addModuleFlag - Add a module-level flag to the module-level flags +/// metadata. It will create the module-level flags named metadata if it doesn't +/// already exist. +void Module::addModuleFlag(ModAttrBehavior Behavior, StringRef Key, +                           Value *Val) { +  Type *Int32Ty = Type::getInt32Ty(Context); +  Value *Ops[3] = { +    ConstantInt::get(Int32Ty, Behavior), MDString::get(Context, Key), Val +  }; +  getOrInsertModuleFlagsMetadata()->addOperand(MDNode::get(Context, Ops)); +} +void Module::addModuleFlag(ModAttrBehavior Behavior, StringRef Key, +                           uint32_t Val) { +  Type *Int32Ty = Type::getInt32Ty(Context); +  addModuleFlag(Behavior, Key, ConstantInt::get(Int32Ty, Val)); +} +void Module::addModuleFlag(MDNode *Node) { +  assert(Node->getNumOperands() == 3 && +         "Invalid number of operands for module flag!"); +  assert(isa<ConstantInt>(Node->getOperand(0)) && +         isa<MDString>(Node->getOperand(1)) && +         "Invalid operand types for module flag!"); +  getOrInsertModuleFlagsMetadata()->addOperand(Node); +}  //===----------------------------------------------------------------------===//  // Methods to control the materialization of GlobalValues in the Module.  | 

