void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {

  ValueInfo VI;
  if (GV.hasName()) {
    VI = ImportIndex.getValueInfo(GV.getGUID());
    // Set synthetic function entry counts.
    if (VI && ImportIndex.hasSyntheticEntryCounts()) {
      if (Function *F = dyn_cast<Function>(&GV)) {
        if (!F->isDeclaration()) {
          for (auto &S : VI.getSummaryList()) {
            FunctionSummary *FS = dyn_cast<FunctionSummary>(S->getBaseObject());
            if (FS->modulePath() == M.getModuleIdentifier()) {
              F->setEntryCount(Function::ProfileCount(FS->entryCount(),
                                                      Function::PCT_Synthetic));
              break;
            }
          }
        }
      }
    }
    // Check the summaries to see if the symbol gets resolved to a known local
    // definition.
    if (VI && VI.isDSOLocal()) {
      GV.setDSOLocal(true);
      if (GV.hasDLLImportStorageClass())
        GV.setDLLStorageClass(GlobalValue::DefaultStorageClass);
    }
  }

  // Mark read-only variables which can be imported with specific attribute.
  // We can't internalize them now because IRMover will fail to link variable
  // definitions to their external declarations during ThinLTO import. We'll
  // internalize read-only variables later, after import is finished.
  // See internalizeImmutableGVs.
  //
  // If global value dead stripping is not enabled in summary then
  // propagateConstants hasn't been run. We can't internalize GV
  // in such case.
  if (!GV.isDeclaration() && VI && ImportIndex.withGlobalValueDeadStripping()) {
    const auto &SL = VI.getSummaryList();
    auto *GVS = SL.empty() ? nullptr : dyn_cast<GlobalVarSummary>(SL[0].get());
    if (GVS && GVS->isReadOnly())
      cast<GlobalVariable>(&GV)->addAttribute("thinlto-internalize");
  }

  bool DoPromote = false;
  if (GV.hasLocalLinkage() &&
      ((DoPromote = shouldPromoteLocalToGlobal(&GV)) || isPerformingImport())) {
    // Save the original name string before we rename GV below.
    auto Name = GV.getName().str();
    // Once we change the name or linkage it is difficult to determine
    // again whether we should promote since shouldPromoteLocalToGlobal needs
    // to locate the summary (based on GUID from name and linkage). Therefore,
    // use DoPromote result saved above.
    GV.setName(getName(&GV, DoPromote));
    GV.setLinkage(getLinkage(&GV, DoPromote));
    if (!GV.hasLocalLinkage())
      GV.setVisibility(GlobalValue::HiddenVisibility);

    // If we are renaming a COMDAT leader, ensure that we record the COMDAT
    // for later renaming as well. This is required for COFF.
    if (const auto *C = GV.getComdat())
      if (C->getName() == Name)
        RenamedComdats.try_emplace(C, M.getOrInsertComdat(GV.getName()));
  } else
    GV.setLinkage(getLinkage(&GV, /* DoPromote */ false));

  // Remove functions imported as available externally defs from comdats,
  // as this is a declaration for the linker, and will be dropped eventually.
  // It is illegal for comdats to contain declarations.
  auto *GO = dyn_cast<GlobalObject>(&GV);
  if (GO && GO->isDeclarationForLinker() && GO->hasComdat()) {
    // The IRMover should not have placed any imported declarations in
    // a comdat, so the only declaration that should be in a comdat
    // at this point would be a definition imported as available_externally.
    assert(GO->hasAvailableExternallyLinkage() &&
           "Expected comdat on definition (possibly available external)");
    GO->setComdat(nullptr);
  }
}
Esempio n. 2
0
bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc,
                                        const GlobalValue &Dest,
                                        const GlobalValue &Src) {

  // Should we unconditionally use the Src?
  if (shouldOverrideFromSrc()) {
    LinkFromSrc = true;
    return false;
  }

  // We always have to add Src if it has appending linkage.
  if (Src.hasAppendingLinkage()) {
    // Should have prevented importing for appending linkage in linkIfNeeded.
    assert(!isPerformingImport());
    LinkFromSrc = true;
    return false;
  }

  if (isPerformingImport()) {
    // LinkFromSrc iff this is a global requested for importing.
    LinkFromSrc = GlobalsToImport->count(&Src);
    return false;
  }

  bool SrcIsDeclaration = Src.isDeclarationForLinker();
  bool DestIsDeclaration = Dest.isDeclarationForLinker();

  if (SrcIsDeclaration) {
    // If Src is external or if both Src & Dest are external..  Just link the
    // external globals, we aren't adding anything.
    if (Src.hasDLLImportStorageClass()) {
      // If one of GVs is marked as DLLImport, result should be dllimport'ed.
      LinkFromSrc = DestIsDeclaration;
      return false;
    }
    // If the Dest is weak, use the source linkage.
    if (Dest.hasExternalWeakLinkage()) {
      LinkFromSrc = true;
      return false;
    }
    // Link an available_externally over a declaration.
    LinkFromSrc = !Src.isDeclaration() && Dest.isDeclaration();
    return false;
  }

  if (DestIsDeclaration) {
    // If Dest is external but Src is not:
    LinkFromSrc = true;
    return false;
  }

  if (Src.hasCommonLinkage()) {
    if (Dest.hasLinkOnceLinkage() || Dest.hasWeakLinkage()) {
      LinkFromSrc = true;
      return false;
    }

    if (!Dest.hasCommonLinkage()) {
      LinkFromSrc = false;
      return false;
    }

    const DataLayout &DL = Dest.getParent()->getDataLayout();
    uint64_t DestSize = DL.getTypeAllocSize(Dest.getValueType());
    uint64_t SrcSize = DL.getTypeAllocSize(Src.getValueType());
    LinkFromSrc = SrcSize > DestSize;
    return false;
  }

  if (Src.isWeakForLinker()) {
    assert(!Dest.hasExternalWeakLinkage());
    assert(!Dest.hasAvailableExternallyLinkage());

    if (Dest.hasLinkOnceLinkage() && Src.hasWeakLinkage()) {
      LinkFromSrc = true;
      return false;
    }

    LinkFromSrc = false;
    return false;
  }

  if (Dest.isWeakForLinker()) {
    assert(Src.hasExternalLinkage());
    LinkFromSrc = true;
    return false;
  }

  assert(!Src.hasExternalWeakLinkage());
  assert(!Dest.hasExternalWeakLinkage());
  assert(Dest.hasExternalLinkage() && Src.hasExternalLinkage() &&
         "Unexpected linkage type!");
  return emitError("Linking globals named '" + Src.getName() +
                   "': symbol multiply defined!");
}
Esempio n. 3
0
bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc,
                                        const GlobalValue &Dest,
                                        const GlobalValue &Src) {

    // Should we unconditionally use the Src?
    if (shouldOverrideFromSrc()) {
        LinkFromSrc = true;
        return false;
    }

    // We always have to add Src if it has appending linkage.
    if (Src.hasAppendingLinkage()) {
        // Should have prevented importing for appending linkage in linkIfNeeded.
        assert(!isPerformingImport());
        LinkFromSrc = true;
        return false;
    }

    bool SrcIsDeclaration = Src.isDeclarationForLinker();
    bool DestIsDeclaration = Dest.isDeclarationForLinker();

    if (isPerformingImport()) {
        if (isa<Function>(&Src)) {
            // For functions, LinkFromSrc iff this is a function requested
            // for importing. For variables, decide below normally.
            LinkFromSrc = GlobalsToImport->count(&Src);
            return false;
        }

        // Check if this is an alias with an already existing definition
        // in Dest, which must have come from a prior importing pass from
        // the same Src module. Unlike imported function and variable
        // definitions, which are imported as available_externally and are
        // not definitions for the linker, that is not a valid linkage for
        // imported aliases which must be definitions. Simply use the existing
        // Dest copy.
        if (isa<GlobalAlias>(&Src) && !DestIsDeclaration) {
            assert(isa<GlobalAlias>(&Dest));
            LinkFromSrc = false;
            return false;
        }
    }

    if (SrcIsDeclaration) {
        // If Src is external or if both Src & Dest are external..  Just link the
        // external globals, we aren't adding anything.
        if (Src.hasDLLImportStorageClass()) {
            // If one of GVs is marked as DLLImport, result should be dllimport'ed.
            LinkFromSrc = DestIsDeclaration;
            return false;
        }
        // If the Dest is weak, use the source linkage.
        if (Dest.hasExternalWeakLinkage()) {
            LinkFromSrc = true;
            return false;
        }
        // Link an available_externally over a declaration.
        LinkFromSrc = !Src.isDeclaration() && Dest.isDeclaration();
        return false;
    }

    if (DestIsDeclaration) {
        // If Dest is external but Src is not:
        LinkFromSrc = true;
        return false;
    }

    if (Src.hasCommonLinkage()) {
        if (Dest.hasLinkOnceLinkage() || Dest.hasWeakLinkage()) {
            LinkFromSrc = true;
            return false;
        }

        if (!Dest.hasCommonLinkage()) {
            LinkFromSrc = false;
            return false;
        }

        const DataLayout &DL = Dest.getParent()->getDataLayout();
        uint64_t DestSize = DL.getTypeAllocSize(Dest.getValueType());
        uint64_t SrcSize = DL.getTypeAllocSize(Src.getValueType());
        LinkFromSrc = SrcSize > DestSize;
        return false;
    }

    if (Src.isWeakForLinker()) {
        assert(!Dest.hasExternalWeakLinkage());
        assert(!Dest.hasAvailableExternallyLinkage());

        if (Dest.hasLinkOnceLinkage() && Src.hasWeakLinkage()) {
            LinkFromSrc = true;
            return false;
        }

        LinkFromSrc = false;
        return false;
    }

    if (Dest.isWeakForLinker()) {
        assert(Src.hasExternalLinkage());
        LinkFromSrc = true;
        return false;
    }

    assert(!Src.hasExternalWeakLinkage());
    assert(!Dest.hasExternalWeakLinkage());
    assert(Dest.hasExternalLinkage() && Src.hasExternalLinkage() &&
           "Unexpected linkage type!");
    return emitError("Linking globals named '" + Src.getName() +
                     "': symbol multiply defined!");
}