예제 #1
0
void IRGenModule::addLinkLibrary(const LinkLibrary &linkLib) {
  llvm::LLVMContext &ctx = Module.getContext();

  switch (linkLib.getKind()) {
  case LibraryKind::Library: {
    llvm::SmallString<32> opt =
        getTargetDependentLibraryOption(Triple, linkLib.getName());
    AutolinkEntries.push_back(
        llvm::MDNode::get(ctx, llvm::MDString::get(ctx, opt)));
    break;
  }
  case LibraryKind::Framework: {
    // If we're supposed to disable autolinking of this framework, bail out.
    auto &frameworks = IRGen.Opts.DisableAutolinkFrameworks;
    if (std::find(frameworks.begin(), frameworks.end(), linkLib.getName())
          != frameworks.end())
      return;

    llvm::Metadata *args[] = {
      llvm::MDString::get(ctx, "-framework"),
      llvm::MDString::get(ctx, linkLib.getName())
    };
    AutolinkEntries.push_back(llvm::MDNode::get(ctx, args));
    break;
  }
  }

  if (linkLib.shouldForceLoad()) {
    llvm::SmallString<64> buf;
    encodeForceLoadSymbolName(buf, linkLib.getName());
    auto ForceImportThunk =
        Module.getOrInsertFunction(buf, llvm::FunctionType::get(VoidTy, false));
    if (useDllStorage())
      cast<llvm::GlobalValue>(ForceImportThunk)
          ->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);

    buf += "_$";
    appendEncodedName(buf, IRGen.Opts.ModuleName);

    if (!Module.getGlobalVariable(buf.str())) {
      auto ref = new llvm::GlobalVariable(Module, ForceImportThunk->getType(),
                                          /*isConstant=*/true,
                                          llvm::GlobalValue::WeakAnyLinkage,
                                          ForceImportThunk, buf.str());
      ref->setVisibility(llvm::GlobalValue::HiddenVisibility);
      auto casted = llvm::ConstantExpr::getBitCast(ref, Int8PtrTy);
      LLVMUsed.push_back(casted);
    }
  }
}
예제 #2
0
void IRGenModule::addLinkLibrary(const LinkLibrary &linkLib) {
  llvm::LLVMContext &ctx = Module.getContext();

  switch (linkLib.getKind()) {
  case LibraryKind::Library: {
    // FIXME: Use target-independent linker option.
    // Clang uses CGM.getTargetCodeGenInfo().getDependentLibraryOption(...).
    llvm::SmallString<32> buf;
    buf += "-l";
    buf += linkLib.getName();
    auto flag = llvm::MDString::get(ctx, buf);
    AutolinkEntries.push_back(llvm::MDNode::get(ctx, flag));
    break;
  }
  case LibraryKind::Framework: {
    // If we're supposed to disable autolinking of this framework, bail out.
    auto &frameworks = IRGen.Opts.DisableAutolinkFrameworks;
    if (std::find(frameworks.begin(), frameworks.end(), linkLib.getName())
          != frameworks.end())
      return;

    llvm::Metadata *args[] = {
      llvm::MDString::get(ctx, "-framework"),
      llvm::MDString::get(ctx, linkLib.getName())
    };
    AutolinkEntries.push_back(llvm::MDNode::get(ctx, args));
    break;
  }
  }

  if (linkLib.shouldForceLoad()) {
    llvm::SmallString<64> buf;
    encodeForceLoadSymbolName(buf, linkLib.getName());
    auto symbolAddr = Module.getOrInsertGlobal(buf.str(), Int1Ty);

    buf += "_$";
    appendEncodedName(buf, IRGen.Opts.ModuleName);

    if (!Module.getGlobalVariable(buf.str())) {
      auto ref = new llvm::GlobalVariable(Module, symbolAddr->getType(),
                                          /*constant=*/true,
                                          llvm::GlobalValue::WeakAnyLinkage,
                                          symbolAddr, buf.str());
      ref->setVisibility(llvm::GlobalValue::HiddenVisibility);
      auto casted = llvm::ConstantExpr::getBitCast(ref, Int8PtrTy);
      LLVMUsed.push_back(casted);
    }
  }
}
예제 #3
0
파일: Immediate.cpp 프로젝트: jxyang/swift
static bool tryLoadLibrary(LinkLibrary linkLib,
                           SearchPathOptions searchPathOpts) {
  llvm::SmallString<128> path = linkLib.getName();

  // If we have an absolute or relative path, just try to load it now.
  if (llvm::sys::path::has_parent_path(path.str())) {
#if WIN32
	  return LoadLibrary(path.c_str());
#else
    return dlopen(path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
#endif
  }

  bool success = false;
  switch (linkLib.getKind()) {
  case LibraryKind::Library: {
    llvm::SmallString<32> stem;
    if (llvm::sys::path::has_extension(path.str())) {
      stem = std::move(path);
    } else {
      // FIXME: Try the appropriate extension for the current platform?
      stem = "lib";
      stem += path;
      stem += LTDL_SHLIB_EXT;
    }

    // Try user-provided library search paths first.
    for (auto &libDir : searchPathOpts.LibrarySearchPaths) {
      path = libDir;
      llvm::sys::path::append(path, stem.str());
#if WIN32
	  success = LoadLibrary(path.c_str());
#else
      success = dlopen(path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
#endif
      if (success)
        break;
    }

    // Let dlopen determine the best search paths.
    if (!success)
#if WIN32
	  success = LoadLibrary(stem.c_str());
#else
      success = dlopen(stem.c_str(), RTLD_LAZY | RTLD_GLOBAL);
#endif

    // If that fails, try our runtime library path.
    if (!success)
      success = loadRuntimeLib(stem, searchPathOpts.RuntimeLibraryPath);
    break;
  }
  case LibraryKind::Framework: {
    // If we have a framework, mangle the name to point to the framework
    // binary.
    llvm::SmallString<64> frameworkPart{std::move(path)};
    frameworkPart += ".framework";
    llvm::sys::path::append(frameworkPart, linkLib.getName());

    // Try user-provided framework search paths first; frameworks contain
    // binaries as well as modules.
    for (auto &frameworkDir : searchPathOpts.FrameworkSearchPaths) {
      path = frameworkDir;
      llvm::sys::path::append(path, frameworkPart.str());
#if WIN32
	  success = LoadLibrary(path.c_str());
#else
      success = dlopen(path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
#endif
      if (success)
        break;
    }

    // If that fails, let dlopen search for system frameworks.
    if (!success)
#if WIN32
	  success = LoadLibrary(frameworkPart.c_str());
#else
      success = dlopen(frameworkPart.c_str(), RTLD_LAZY | RTLD_GLOBAL);
#endif
    break;
  }
  }

  return success;
}