当前位置: 首页>>代码示例>>C++>>正文


C++ LLVMContext类代码示例

本文整理汇总了C++中LLVMContext的典型用法代码示例。如果您正苦于以下问题:C++ LLVMContext类的具体用法?C++ LLVMContext怎么用?C++ LLVMContext使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。


在下文中一共展示了LLVMContext类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: Context

LTOCodeGenerator::LTOCodeGenerator(LLVMContext &Context)
    : Context(Context), MergedModule(new Module("ld-temp.o", Context)),
      TheLinker(new Linker(*MergedModule)) {
  Context.setDiscardValueNames(LTODiscardValueNames);
  Context.enableDebugTypeODRUniquing();
  initializeLTOPasses();
}
开发者ID:Wilfred,项目名称:llvm,代码行数:7,代码来源:LTOCodeGenerator.cpp

示例2: main

int main(int argc, char **argv) {
  // Print a stack trace if we signal out.
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(argc, argv);

  LLVMContext Context;
  Context.setDiagnosticHandler(diagnosticHandlerWithContext, nullptr, true);

  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
  cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");

  auto Composite = make_unique<Module>("llvm-link", Context);
  Linker L(*Composite);

  unsigned Flags = Linker::Flags::None;
  if (Internalize)
    Flags |= Linker::Flags::InternalizeLinkedSymbols;
  if (OnlyNeeded)
    Flags |= Linker::Flags::LinkOnlyNeeded;

  // First add all the regular input files
  if (!linkFiles(argv[0], Context, L, InputFilenames, Flags))
    return 1;

  // Next the -override ones.
  if (!linkFiles(argv[0], Context, L, OverridingInputs,
                 Flags | Linker::Flags::OverrideFromSrc))
    return 1;

  // Import any functions requested via -import
  if (!importFunctions(argv[0], Context, L))
    return 1;

  if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite;

  std::error_code EC;
  tool_output_file Out(OutputFilename, EC, sys::fs::F_None);
  if (EC) {
    errs() << EC.message() << '\n';
    return 1;
  }

  if (verifyModule(*Composite, &errs())) {
    errs() << argv[0] << ": error: linked module is broken!\n";
    return 1;
  }

  if (Verbose) errs() << "Writing bitcode...\n";
  if (OutputAssembly) {
    Composite->print(Out.os(), nullptr, PreserveAssemblyUseListOrder);
  } else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true))
    WriteBitcodeToFile(Composite.get(), Out.os(), PreserveBitcodeUseListOrder);

  // Declare success.
  Out.keep();

  return 0;
}
开发者ID:zoren,项目名称:llvm,代码行数:58,代码来源:llvm-link.cpp

示例3: main

int main(int argc, char **argv) {
  // Print a stack trace if we signal out.
  sys::PrintStackTraceOnErrorSignal(argv[0]);
  PrettyStackTraceProgram X(argc, argv);

  LLVMContext Context;
  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.

  Context.setDiagnosticHandler(diagnosticHandler, argv[0]);

  cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");

  Expected<std::unique_ptr<Module>> MOrErr = openInputFile(Context);
  if (!MOrErr) {
    handleAllErrors(MOrErr.takeError(), [&](ErrorInfoBase &EIB) {
      errs() << argv[0] << ": ";
      EIB.log(errs());
      errs() << '\n';
    });
    return 1;
  }
  std::unique_ptr<Module> M = std::move(*MOrErr);

  // Just use stdout.  We won't actually print anything on it.
  if (DontPrint)
    OutputFilename = "-";

  if (OutputFilename.empty()) { // Unspecified output, infer it.
    if (InputFilename == "-") {
      OutputFilename = "-";
    } else {
      StringRef IFN = InputFilename;
      OutputFilename = (IFN.endswith(".bc") ? IFN.drop_back(3) : IFN).str();
      OutputFilename += ".ll";
    }
  }

  std::error_code EC;
  std::unique_ptr<tool_output_file> Out(
      new tool_output_file(OutputFilename, EC, sys::fs::F_None));
  if (EC) {
    errs() << EC.message() << '\n';
    return 1;
  }

  std::unique_ptr<AssemblyAnnotationWriter> Annotator;
  if (ShowAnnotations)
    Annotator.reset(new CommentWriter());

  // All that llvm-dis does is write the assembly to a file.
  if (!DontPrint)
    M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder);

  // Declare success.
  Out->keep();

  return 0;
}
开发者ID:CSI-LLVM,项目名称:llvm,代码行数:58,代码来源:llvm-dis.cpp

示例4: linkCombinedIndex

// Main entry point for the ThinLTO processing
void ThinLTOCodeGenerator::run() {
  // Sequential linking phase
  auto Index = linkCombinedIndex();

  // Save temps: index.
  if (!SaveTempsDir.empty()) {
    auto SaveTempPath = SaveTempsDir + "index.bc";
    std::error_code EC;
    raw_fd_ostream OS(SaveTempPath, EC, sys::fs::F_None);
    if (EC)
      report_fatal_error(Twine("Failed to open ") + SaveTempPath +
                         " to save optimized bitcode\n");
    WriteIndexToFile(*Index, OS);
  }

  // Prepare the resulting object vector
  assert(ProducedBinaries.empty() && "The generator should not be reused");
  ProducedBinaries.resize(Modules.size());

  // Prepare the module map.
  auto ModuleMap = generateModuleMap(Modules);

  // Parallel optimizer + codegen
  {
    ThreadPool Pool(ThreadCount);
    int count = 0;
    for (auto &ModuleBuffer : Modules) {
      Pool.async([&](int count) {
        LLVMContext Context;
        Context.setDiscardValueNames(LTODiscardValueNames);

        // Parse module now
        auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context, false);

        // Save temps: original file.
        if (!SaveTempsDir.empty()) {
          saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc");
        }

        ProducedBinaries[count] = ProcessThinLTOModule(
            *TheModule, *Index, ModuleMap, *TMBuilder.create(), CacheOptions,
            SaveTempsDir, count);
      }, count);
      count++;
    }
  }

  // If statistics were requested, print them out now.
  if (llvm::AreStatisticsEnabled())
    llvm::PrintStatistics();
}
开发者ID:liugundam,项目名称:llvm,代码行数:52,代码来源:ThinLTOCodeGenerator.cpp

示例5: SMDiagnostic

std::unique_ptr<MIRParser>
llvm::createMIRParser(std::unique_ptr<MemoryBuffer> Contents,
                      LLVMContext &Context) {
  auto Filename = Contents->getBufferIdentifier();
  if (Context.shouldDiscardValueNames()) {
    Context.diagnose(DiagnosticInfoMIRParser(
        DS_Error,
        SMDiagnostic(
            Filename, SourceMgr::DK_Error,
            "Can't read MIR with a Context that discards named Values")));
    return nullptr;
  }
  return llvm::make_unique<MIRParser>(
      llvm::make_unique<MIRParserImpl>(std::move(Contents), Filename, Context));
}
开发者ID:a565109863,项目名称:src,代码行数:15,代码来源:MIRParser.cpp

示例6: emitOptimizationRemarkAnalysis

void llvm::emitOptimizationRemarkAnalysis(LLVMContext &Ctx,
                                          const char *PassName,
                                          const Function &Fn,
                                          const DebugLoc &DLoc,
                                          const Twine &Msg) {
  Ctx.diagnose(
      DiagnosticInfoOptimizationRemarkAnalysis(PassName, Fn, DLoc, Msg));
}
开发者ID:A2-Collaboration,项目名称:root,代码行数:8,代码来源:DiagnosticInfo.cpp

示例7: main

// main - Entry point for the llc compiler.
//
int main(int argc, char **argv) {
  sys::PrintStackTraceOnErrorSignal(argv[0]);
  PrettyStackTraceProgram X(argc, argv);

  // Enable debug stream buffering.
  EnableDebugBuffering = true;

  LLVMContext Context;
  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.

  // Initialize targets first, so that --version shows registered targets.
  InitializeAllTargets();
  InitializeAllTargetMCs();
  InitializeAllAsmPrinters();
  InitializeAllAsmParsers();

  // Initialize codegen and IR passes used by llc so that the -print-after,
  // -print-before, and -stop-after options work.
  PassRegistry *Registry = PassRegistry::getPassRegistry();
  initializeCore(*Registry);
  initializeCodeGen(*Registry);
  initializeLoopStrengthReducePass(*Registry);
  initializeLowerIntrinsicsPass(*Registry);
  initializeCountingFunctionInserterPass(*Registry);
  initializeUnreachableBlockElimLegacyPassPass(*Registry);
  initializeConstantHoistingLegacyPassPass(*Registry);

  // Register the target printer for --version.
  cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);

  cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");

  Context.setDiscardValueNames(DiscardValueNames);

  // Set a diagnostic handler that doesn't exit on the first error
  bool HasError = false;
  Context.setDiagnosticHandler(DiagnosticHandler, &HasError);

  // Compile the module TimeCompilations times to give better compile time
  // metrics.
  for (unsigned I = TimeCompilations; I; --I)
    if (int RetVal = compileModule(argv, Context))
      return RetVal;
  return 0;
}
开发者ID:efcs,项目名称:llvm,代码行数:47,代码来源:llc.cpp

示例8: thinLTOBackendTask

/// Perform the ThinLTO backend on a single module, invoking the LTO and codegen
/// pipelines.
static void thinLTOBackendTask(claimed_file &F, const void *View,
                               ld_plugin_input_file &File,
                               raw_fd_ostream *ApiFile,
                               const ModuleSummaryIndex &CombinedIndex,
                               raw_fd_ostream *OS, unsigned TaskID) {
  // Need to use a separate context for each task
  LLVMContext Context;
  Context.setDiagnosticHandler(diagnosticHandlerForContext, nullptr, true);

  std::unique_ptr<llvm::Module> NewModule(new llvm::Module(File.name, Context));
  IRMover L(*NewModule.get());

  StringSet<> Dummy;
  if (linkInModule(Context, L, F, View, File, ApiFile, Dummy, Dummy))
    message(LDPL_FATAL, "Failed to rename module for ThinLTO");
  if (renameModuleForThinLTO(*NewModule, CombinedIndex))
    message(LDPL_FATAL, "Failed to rename module for ThinLTO");

  CodeGen codeGen(std::move(NewModule), OS, TaskID, &CombinedIndex, File.name);
  codeGen.runAll();
}
开发者ID:AlexDenisov,项目名称:llvm,代码行数:23,代码来源:gold-plugin.cpp

示例9: makeLTOModule

ErrorOr<std::unique_ptr<LTOModule>>
LTOModule::createFromFile(LLVMContext &Context, StringRef path,
                          const TargetOptions &options) {
  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
      MemoryBuffer::getFile(path);
  if (std::error_code EC = BufferOrErr.getError()) {
    Context.emitError(EC.message());
    return EC;
  }
  std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrErr.get());
  return makeLTOModule(Buffer->getMemBufferRef(), options, Context,
                       /* ShouldBeLazy*/ false);
}
开发者ID:anupam128,项目名称:llvm,代码行数:13,代码来源:LTOModule.cpp

示例10: printSyncScope

void MIPrinter::printSyncScope(const LLVMContext &Context, SyncScope::ID SSID) {
  switch (SSID) {
  case SyncScope::System: {
    break;
  }
  default: {
    if (SSNs.empty())
      Context.getSyncScopeNames(SSNs);

    OS << "syncscope(\"";
    PrintEscapedString(SSNs[SSID], OS);
    OS << "\") ";
    break;
  }
  }
}
开发者ID:a565109863,项目名称:src,代码行数:16,代码来源:MIRPrinter.cpp

示例11: printSyncScope

static void printSyncScope(raw_ostream &OS, const LLVMContext &Context,
                           SyncScope::ID SSID,
                           SmallVectorImpl<StringRef> &SSNs) {
  switch (SSID) {
  case SyncScope::System:
    break;
  default:
    if (SSNs.empty())
      Context.getSyncScopeNames(SSNs);

    OS << "syncscope(\"";
    printEscapedString(SSNs[SSID], OS);
    OS << "\") ";
    break;
  }
}
开发者ID:CTSRD-CHERI,项目名称:llvm,代码行数:16,代码来源:MachineOperand.cpp

示例12: parseBitcodeFileImpl

static ErrorOr<std::unique_ptr<Module>>
parseBitcodeFileImpl(MemoryBufferRef Buffer, LLVMContext &Context,
                     bool ShouldBeLazy) {

  // Find the buffer.
  ErrorOr<MemoryBufferRef> MBOrErr =
      IRObjectFile::findBitcodeInMemBuffer(Buffer);
  if (std::error_code EC = MBOrErr.getError()) {
    Context.emitError(EC.message());
    return EC;
  }

  if (!ShouldBeLazy) {
    // Parse the full file.
    return expectedToErrorOrAndEmitErrors(Context,
                                          parseBitcodeFile(*MBOrErr, Context));
  }

  // Parse lazily.
  return expectedToErrorOrAndEmitErrors(
      Context,
      getLazyBitcodeModule(*MBOrErr, Context, true /*ShouldLazyLoadMetadata*/));
}
开发者ID:anupam128,项目名称:llvm,代码行数:23,代码来源:LTOModule.cpp

示例13: compileModule

static int compileModule(char **argv, LLVMContext &Context) {
  // Load the module to be compiled...
  SMDiagnostic Err;
  std::unique_ptr<Module> M;
  std::unique_ptr<MIRParser> MIR;
  Triple TheTriple;

  bool SkipModule = MCPU == "help" ||
                    (!MAttrs.empty() && MAttrs.front() == "help");

  // If user just wants to list available options, skip module loading
  if (!SkipModule) {
    if (StringRef(InputFilename).endswith_lower(".mir")) {
      MIR = createMIRParserFromFile(InputFilename, Err, Context);
      if (MIR)
        M = MIR->parseLLVMModule();
    } else
      M = parseIRFile(InputFilename, Err, Context);
    if (!M) {
      Err.print(argv[0], errs());
      return 1;
    }

    // Verify module immediately to catch problems before doInitialization() is
    // called on any passes.
    if (!NoVerify && verifyModule(*M, &errs())) {
      errs() << argv[0] << ": " << InputFilename
             << ": error: input module is broken!\n";
      return 1;
    }

    // If we are supposed to override the target triple, do so now.
    if (!TargetTriple.empty())
      M->setTargetTriple(Triple::normalize(TargetTriple));
    TheTriple = Triple(M->getTargetTriple());
  } else {
    TheTriple = Triple(Triple::normalize(TargetTriple));
  }

  if (TheTriple.getTriple().empty())
    TheTriple.setTriple(sys::getDefaultTargetTriple());

  // Get the target specific parser.
  std::string Error;
  const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple,
                                                         Error);
  if (!TheTarget) {
    errs() << argv[0] << ": " << Error;
    return 1;
  }

  std::string CPUStr = getCPUStr(), FeaturesStr = getFeaturesStr();

  CodeGenOpt::Level OLvl = CodeGenOpt::Default;
  switch (OptLevel) {
  default:
    errs() << argv[0] << ": invalid optimization level.\n";
    return 1;
  case ' ': break;
  case '0': OLvl = CodeGenOpt::None; break;
  case '1': OLvl = CodeGenOpt::Less; break;
  case '2': OLvl = CodeGenOpt::Default; break;
  case '3': OLvl = CodeGenOpt::Aggressive; break;
  }

  TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
  Options.DisableIntegratedAS = NoIntegratedAssembler;
  Options.MCOptions.ShowMCEncoding = ShowMCEncoding;
  Options.MCOptions.MCUseDwarfDirectory = EnableDwarfDirectory;
  Options.MCOptions.AsmVerbose = AsmVerbose;
  Options.MCOptions.PreserveAsmComments = PreserveComments;
  Options.MCOptions.IASSearchPaths = IncludeDirs;

  std::unique_ptr<TargetMachine> Target(
      TheTarget->createTargetMachine(TheTriple.getTriple(), CPUStr, FeaturesStr,
                                     Options, getRelocModel(), CMModel, OLvl));

  assert(Target && "Could not allocate target machine!");

  // If we don't have a module then just exit now. We do this down
  // here since the CPU/Feature help is underneath the target machine
  // creation.
  if (SkipModule)
    return 0;

  assert(M && "Should have exited if we didn't have a module!");
  if (FloatABIForCalls != FloatABI::Default)
    Options.FloatABIType = FloatABIForCalls;

  // Figure out where we are going to send the output.
  std::unique_ptr<tool_output_file> Out =
      GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]);
  if (!Out) return 1;

  // Build up all of the passes that we want to do to the module.
  legacy::PassManager PM;

  // Add an appropriate TargetLibraryInfo pass for the module's triple.
  TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));

//.........这里部分代码省略.........
开发者ID:,项目名称:,代码行数:101,代码来源:

示例14: main

// main - Entry point for the llc compiler.
//
int main(int argc, char **argv) {
  sys::PrintStackTraceOnErrorSignal(argv[0]);
  PrettyStackTraceProgram X(argc, argv);

  // Enable debug stream buffering.
  EnableDebugBuffering = true;

  LLVMContext Context;
  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.

  // Initialize targets first, so that --version shows registered targets.
  InitializeAllTargets();
  InitializeAllTargetMCs();
  InitializeAllAsmPrinters();
  InitializeAllAsmParsers();

  // Initialize codegen and IR passes used by llc so that the -print-after,
  // -print-before, and -stop-after options work.
  PassRegistry *Registry = PassRegistry::getPassRegistry();
  initializeCore(*Registry);
  initializeCodeGen(*Registry);
  initializeLoopStrengthReducePass(*Registry);
  initializeLowerIntrinsicsPass(*Registry);
  initializeCountingFunctionInserterPass(*Registry);
  initializeUnreachableBlockElimLegacyPassPass(*Registry);
  initializeConstantHoistingLegacyPassPass(*Registry);
  initializeScalarOpts(*Registry);
  initializeVectorization(*Registry);

  // Register the target printer for --version.
  cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);

  cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");

  Context.setDiscardValueNames(DiscardValueNames);

  // Set a diagnostic handler that doesn't exit on the first error
  bool HasError = false;
  Context.setDiagnosticHandler(DiagnosticHandler, &HasError);
  Context.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, &HasError);

  if (PassRemarksWithHotness)
    Context.setDiagnosticHotnessRequested(true);

  std::unique_ptr<tool_output_file> YamlFile;
  if (RemarksFilename != "") {
    std::error_code EC;
    YamlFile = llvm::make_unique<tool_output_file>(RemarksFilename, EC,
                                                   sys::fs::F_None);
    if (EC) {
      errs() << EC.message() << '\n';
      return 1;
    }
    Context.setDiagnosticsOutputFile(
        llvm::make_unique<yaml::Output>(YamlFile->os()));
  }

  // Compile the module TimeCompilations times to give better compile time
  // metrics.
  for (unsigned I = TimeCompilations; I; --I)
    if (int RetVal = compileModule(argv, Context))
      return RetVal;

  if (YamlFile)
    YamlFile->keep();
  return 0;
}
开发者ID:,项目名称:,代码行数:69,代码来源:

示例15: allSymbolsReadHook

/// gold informs us that all symbols have been read. At this point, we use
/// get_symbols to see if any of our definitions have been overridden by a
/// native object file. Then, perform optimization and codegen.
static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) {
  if (Modules.empty())
    return LDPS_OK;

  LLVMContext Context;
  Context.setDiagnosticHandler(diagnosticHandler, nullptr, true);

  // If we are doing ThinLTO compilation, simply build the combined
  // function index/summary and emit it. We don't need to parse the modules
  // and link them in this case.
  if (options::thinlto) {
    std::unique_ptr<FunctionInfoIndex> CombinedIndex(new FunctionInfoIndex());
    uint64_t NextModuleId = 0;
    for (claimed_file &F : Modules) {
      ld_plugin_input_file File;
      if (get_input_file(F.handle, &File) != LDPS_OK)
        message(LDPL_FATAL, "Failed to get file information");

      std::unique_ptr<FunctionInfoIndex> Index =
          getFunctionIndexForFile(Context, F, File);
      CombinedIndex->mergeFrom(std::move(Index), ++NextModuleId);
    }

    std::error_code EC;
    raw_fd_ostream OS(output_name + ".thinlto.bc", EC,
                      sys::fs::OpenFlags::F_None);
    if (EC)
      message(LDPL_FATAL, "Unable to open %s.thinlto.bc for writing: %s",
              output_name.data(), EC.message().c_str());
    WriteFunctionSummaryToFile(CombinedIndex.get(), OS);
    OS.close();

    cleanup_hook();
    exit(0);
  }

  std::unique_ptr<Module> Combined(new Module("ld-temp.o", Context));
  Linker L(Combined.get());

  std::string DefaultTriple = sys::getDefaultTargetTriple();

  StringSet<> Internalize;
  StringSet<> Maybe;
  for (claimed_file &F : Modules) {
    ld_plugin_input_file File;
    if (get_input_file(F.handle, &File) != LDPS_OK)
      message(LDPL_FATAL, "Failed to get file information");
    std::unique_ptr<Module> M =
        getModuleForFile(Context, F, File, ApiFile, Internalize, Maybe);
    if (!options::triple.empty())
      M->setTargetTriple(options::triple.c_str());
    else if (M->getTargetTriple().empty()) {
      M->setTargetTriple(DefaultTriple);
    }

    if (L.linkInModule(M.get()))
      message(LDPL_FATAL, "Failed to link module");
    if (release_input_file(F.handle) != LDPS_OK)
      message(LDPL_FATAL, "Failed to release file information");
  }

  for (const auto &Name : Internalize) {
    GlobalValue *GV = Combined->getNamedValue(Name.first());
    if (GV)
      internalize(*GV);
  }

  for (const auto &Name : Maybe) {
    GlobalValue *GV = Combined->getNamedValue(Name.first());
    if (!GV)
      continue;
    GV->setLinkage(GlobalValue::LinkOnceODRLinkage);
    if (canBeOmittedFromSymbolTable(GV))
      internalize(*GV);
  }

  if (options::TheOutputType == options::OT_DISABLE)
    return LDPS_OK;

  if (options::TheOutputType != options::OT_NORMAL) {
    std::string path;
    if (options::TheOutputType == options::OT_BC_ONLY)
      path = output_name;
    else
      path = output_name + ".bc";
    saveBCFile(path, *L.getModule());
    if (options::TheOutputType == options::OT_BC_ONLY)
      return LDPS_OK;
  }

  codegen(std::move(Combined));

  if (!options::extra_library_path.empty() &&
      set_extra_library_path(options::extra_library_path.c_str()) != LDPS_OK)
    message(LDPL_FATAL, "Unable to set the extra library path.");

  return LDPS_OK;
//.........这里部分代码省略.........
开发者ID:nightwishud,项目名称:accmut,代码行数:101,代码来源:gold-plugin.cpp


注:本文中的LLVMContext类示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。