Author: 董⼀峰 Date: 2021-07-13T18:22:28+08:00 New Revision: 26c2169a10989277ff01b9f1d3c44a1ab4cbfd9c
URL: https://github.com/llvm/llvm-project/commit/26c2169a10989277ff01b9f1d3c44a1ab4cbfd9c DIFF: https://github.com/llvm/llvm-project/commit/26c2169a10989277ff01b9f1d3c44a1ab4cbfd9c.diff LOG: add some comment for jit component Added: llvm/examples/OrcV2Examples/LLJITWithReexports/CMakeLists.txt llvm/examples/OrcV2Examples/LLJITWithReexports/LLJITWithReexports.cpp Modified: llvm/examples/HowToUseLLJIT/HowToUseLLJIT.cpp llvm/examples/OrcV2Examples/CMakeLists.txt llvm/examples/OrcV2Examples/ExampleModules.h llvm/examples/OrcV2Examples/LLJITWithLazyReexports/LLJITWithLazyReexports.cpp llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h llvm/include/llvm/ExecutionEngine/Orc/Core.h llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp llvm/lib/ExecutionEngine/JITLink/ELF.cpp llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp llvm/lib/ExecutionEngine/Orc/Core.cpp llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp llvm/lib/ExecutionEngine/Orc/LLJIT.cpp llvm/lib/ExecutionEngine/Orc/Layer.cpp llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp Removed: ################################################################################ diff --git a/llvm/examples/HowToUseLLJIT/HowToUseLLJIT.cpp b/llvm/examples/HowToUseLLJIT/HowToUseLLJIT.cpp index 170a899136054..c3ab7e6c1adb8 100644 --- a/llvm/examples/HowToUseLLJIT/HowToUseLLJIT.cpp +++ b/llvm/examples/HowToUseLLJIT/HowToUseLLJIT.cpp @@ -40,7 +40,7 @@ ExitOnError ExitOnErr; ThreadSafeModule createDemoModule() { auto Context = std::make_unique<LLVMContext>(); - auto M = std::make_unique<Module>("test", *Context); +xo auto M = std::make_unique<Module>("test", *Context); // Create the add1 function entry and insert this entry into module M. The // function will have a return type of "int" and take an argument of "int". diff --git a/llvm/examples/OrcV2Examples/CMakeLists.txt b/llvm/examples/OrcV2Examples/CMakeLists.txt index 59311f8fbf1c0..6ea3555db4dcd 100644 --- a/llvm/examples/OrcV2Examples/CMakeLists.txt +++ b/llvm/examples/OrcV2Examples/CMakeLists.txt @@ -2,6 +2,7 @@ add_subdirectory(LLJITDumpObjects) add_subdirectory(LLJITWithCustomObjectLinkingLayer) add_subdirectory(LLJITWithGDBRegistrationListener) add_subdirectory(LLJITWithInitializers) +add_subdirectory(LLJITWithReexports) add_subdirectory(LLJITWithLazyReexports) add_subdirectory(LLJITWithObjectCache) add_subdirectory(LLJITWithObjectLinkingLayerPlugin) diff --git a/llvm/examples/OrcV2Examples/ExampleModules.h b/llvm/examples/OrcV2Examples/ExampleModules.h index 53da756e15f78..a59d8ab042daf 100644 --- a/llvm/examples/OrcV2Examples/ExampleModules.h +++ b/llvm/examples/OrcV2Examples/ExampleModules.h @@ -24,11 +24,80 @@ const llvm::StringRef Add1Example = R"( - define i32 @add1(i32 %x) { - entry: - %r = add nsw i32 %x, 1 - ret i32 %r - } + +; Function Attrs: noinline nounwind optnone ssp uwtable +define i32 @op1(i32 %0, i32 %1) { + %3 = alloca i32, align 4 + %4 = alloca i32, align 4 + store i32 %0, i32* %3, align 4 + store i32 %1, i32* %4, align 4 + %5 = load i32, i32* %3, align 4 + %6 = load i32, i32* %4, align 4 + %7 = add nsw i32 %5, %6 + ret i32 %7 +} + +; Function Attrs: noinline nounwind optnone ssp uwtable +define i32 @op2(i32 %0, i32 %1) { + %3 = alloca i32, align 4 + %4 = alloca i32, align 4 + store i32 %0, i32* %3, align 4 + store i32 %1, i32* %4, align 4 + %5 = load i32, i32* %3, align 4 + %6 = load i32, i32* %4, align 4 + %7 = mul nsw i32 %5, %6 + ret i32 %7 +} + +; Function Attrs: noinline nounwind optnone ssp uwtable +define i32 @add1(i32 %0, i32 %1) { + %3 = alloca i32, align 4 + %4 = alloca i32, align 4 + %5 = alloca i32, align 4 + store i32 %0, i32* %4, align 4 + store i32 %1, i32* %5, align 4 + %6 = load i32, i32* %4, align 4 + %7 = load i32, i32* %5, align 4 + %8 = sub nsw i32 %6, %7 + %9 = icmp sgt i32 %8, 0 + br i1 %9, label %10, label %14 + +10: ; preds = %2 + %11 = load i32, i32* %4, align 4 + %12 = load i32, i32* %5, align 4 + %13 = call i32 @op1(i32 %11, i32 %12) + store i32 %13, i32* %3, align 4 + br label %28 + +14: ; preds = %2 + %15 = load i32, i32* %4, align 4 + %16 = load i32, i32* %5, align 4 + %17 = srem i32 %15, %16 + %18 = icmp eq i32 %17, 2 + br i1 %18, label %19, label %23 + +19: ; preds = %14 + %20 = load i32, i32* %4, align 4 + %21 = load i32, i32* %5, align 4 + %22 = call i32 @op2(i32 %20, i32 %21) + store i32 %22, i32* %3, align 4 + br label %28 + +23: ; preds = %14 + br label %24 + +24: ; preds = %23 + %25 = load i32, i32* %4, align 4 + %26 = load i32, i32* %5, align 4 + %27 = sub nsw i32 %25, %26 + store i32 %27, i32* %3, align 4 + br label %28 + +28: ; preds = %24, %19, %10 + %29 = load i32, i32* %3, align 4 + ret i32 %29 +} + )"; inline llvm::Error createSMDiagnosticError(llvm::SMDiagnostic &Diag) { diff --git a/llvm/examples/OrcV2Examples/LLJITWithLazyReexports/LLJITWithLazyReexports.cpp b/llvm/examples/OrcV2Examples/LLJITWithLazyReexports/LLJITWithLazyReexports.cpp index 5d4a27c432436..1d22a31ef2cf3 100644 --- a/llvm/examples/OrcV2Examples/LLJITWithLazyReexports/LLJITWithLazyReexports.cpp +++ b/llvm/examples/OrcV2Examples/LLJITWithLazyReexports/LLJITWithLazyReexports.cpp @@ -131,12 +131,12 @@ int main(int argc, char *argv[]) { // (5) Add lazy reexports. MangleAndInterner Mangle(J->getExecutionSession(), J->getDataLayout()); - SymbolAliasMap ReExports( + SymbolAliasMap ReExports( // {{Mangle("foo"), - {Mangle("foo_body"), + {Mangle("foo_body"), // foo 等价于foo_body JITSymbolFlags::Exported | JITSymbolFlags::Callable}}, {Mangle("bar"), - {Mangle("bar_body"), + {Mangle("bar_body"), // bar等价于bar_body JITSymbolFlags::Exported | JITSymbolFlags::Callable}}}); ExitOnErr(J->getMainJITDylib().define( lazyReexports(*LCTM, *ISM, J->getMainJITDylib(), std::move(ReExports)))); diff --git a/llvm/examples/OrcV2Examples/LLJITWithReexports/CMakeLists.txt b/llvm/examples/OrcV2Examples/LLJITWithReexports/CMakeLists.txt new file mode 100644 index 0000000000000..006580a108dbd --- /dev/null +++ b/llvm/examples/OrcV2Examples/LLJITWithReexports/CMakeLists.txt @@ -0,0 +1,12 @@ +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + IRReader + OrcJIT + Support + nativecodegen + ) + +add_llvm_example(LLJITWithReexports + LLJITWithReexports.cpp + ) diff --git a/llvm/examples/OrcV2Examples/LLJITWithReexports/LLJITWithReexports.cpp b/llvm/examples/OrcV2Examples/LLJITWithReexports/LLJITWithReexports.cpp new file mode 100644 index 0000000000000..f4597db07c766 --- /dev/null +++ b/llvm/examples/OrcV2Examples/LLJITWithReexports/LLJITWithReexports.cpp @@ -0,0 +1,149 @@ +//===--- LLJITWithLazyReexports.cpp - LLJIT example with custom laziness --===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// In this example we will use the lazy re-exports utility to lazily compile +// IR modules. We will do this in seven steps: +// +// 1. Create an LLJIT instance. +// 2. Install a transform so that we can see what is being compiled. +// 3. Create an indirect stubs manager and lazy call-through manager. +// 4. Add two modules that will be conditionally compiled, plus a main module. +// 5. Add lazy-rexports of the symbols in the conditionally compiled modules. +// 6. Dump the ExecutionSession state to see the symbol table prior to +// executing any code. +// 7. Verify that only modules containing executed code are compiled. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringMap.h" +#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/LLJIT.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/Support/InitLLVM.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" + +#include "../ExampleModules.h" + +using namespace llvm; +using namespace llvm::orc; + +ExitOnError ExitOnErr; + +// Example IR modules. +// +// Note that in the conditionally compiled modules, FooMod and BarMod, functions +// have been given an _body suffix. This is to ensure that their names do not +// clash with their lazy-reexports. +// For clients who do not wish to rename function bodies (e.g. because they want +// to re-use cached objects between static and JIT compiles) techniques exist to +// avoid renaming. See the lazy-reexports section of the ORCv2 design doc. + +const llvm::StringRef FooMod = + R"( + define i32 @foo_body() { + entry: + ret i32 1 + } +)"; + +const llvm::StringRef BarMod = + R"( + define i32 @bar_body() { + entry: + ret i32 2 + } +)"; + +const llvm::StringRef MainMod = + R"( + + define i32 @entry(i32 %argc) { + entry: + %and = and i32 %argc, 1 + %tobool = icmp eq i32 %and, 0 + br i1 %tobool, label %if.end, label %if.then + + if.then: ; preds = %entry + %call = tail call i32 @foo() #2 + br label %return + + if.end: ; preds = %entry + %call1 = tail call i32 @bar() #2 + br label %return + + return: ; preds = %if.end, %if.then + %retval.0 = phi i32 [ %call, %if.then ], [ %call1, %if.end ] + ret i32 %retval.0 + } + + declare i32 @foo() + declare i32 @bar() +)"; + +cl::list<std::string> InputArgv(cl::Positional, + cl::desc("<program arguments>...")); + +int main(int argc, char *argv[]) { + // Initialize LLVM. + InitLLVM X(argc, argv); + + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + + cl::ParseCommandLineOptions(argc, argv, "LLJITWithReexports"); + ExitOnErr.setBanner(std::string(argv[0]) + ": "); + + // (1) Create LLJIT instance. + auto J = ExitOnErr(LLJITBuilder().create()); + + // (2) Install transform to print modules as they are compiled: + J->getIRTransformLayer().setTransform( + [](ThreadSafeModule TSM, + MaterializationResponsibility &R) -> Expected<ThreadSafeModule> { + TSM.withModuleDo([](Module &M) { + dbgs() << "-----Compiling---\n" << M; + }); + return std::move(TSM); + }); + + // (4) Add modules. + ExitOnErr(J->addIRModule(ExitOnErr(parseExampleModule(FooMod, "foo-mod")))); + ExitOnErr(J->addIRModule(ExitOnErr(parseExampleModule(BarMod, "bar-mod")))); + ExitOnErr(J->addIRModule(ExitOnErr(parseExampleModule(MainMod, "main-mod")))); + + // (5) Add lazy reexports. + MangleAndInterner Mangle(J->getExecutionSession(), J->getDataLayout()); + ExitOnErr(J->getMainJITDylib().define( + symbolAliases({{Mangle("foo"), + {Mangle("foo_body"), + JITSymbolFlags::Exported | JITSymbolFlags::Callable}}, + {Mangle("bar"), + {Mangle("bar_body"), JITSymbolFlags::Exported | + JITSymbolFlags::Callable}}}))); + + // (6) Dump the ExecutionSession state. + dbgs() << "---Session state---\n"; + J->getExecutionSession().dump(dbgs()); + dbgs() << "\n"; + + // (7) Execute the JIT'd main function and pass the example's command line + // arguments unmodified. This should cause either ExampleMod1 or ExampleMod2 + // to be compiled, and either "1" or "2" returned depending on the number of + // arguments passed. + + // Look up the JIT'd function, cast it to a function pointer, then call it. + auto EntrySym = ExitOnErr(J->lookup("entry")); + auto *Entry = (int (*)(int))EntrySym.getAddress(); + + int Result = Entry(argc); + outs() << "---Result---\n" + << "entry(" << argc << ") = " << Result << "\n"; + + return 0; +} diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h index 15b5286b869a6..46808d4c7bdea 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h @@ -226,7 +226,7 @@ class Block : public Addressable { /// Get the content for this block. Block must not be a zero-fill block. ArrayRef<char> getContent() const { assert(Data && "Section does not contain content"); - return ArrayRef<char>(Data, Size); + return ArrayRef<char>(Data, Size); // ?????? } /// Set the content for this block. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h index 42bcffd36b25a..a7a07c86af592 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h @@ -880,6 +880,8 @@ class LookupState { std::unique_ptr<InProgressLookupState> IPLS; }; +/// 如果JITDylib在生成新的符号定义的时候, 没有办法找到对应的函数定义。 +/// 那么JIT会调用当前lib上附加的DefinitionGenerator, 作为解析符号的最后手段。 /// Definition generators can be attached to JITDylibs to generate new /// definitions for otherwise unresolved symbols during lookup. class DefinitionGenerator { diff --git a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp index c85e80b52e5ae..66f03e84e42e4 100644 --- a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp @@ -23,7 +23,7 @@ EHFrameSplitter::EHFrameSplitter(StringRef EHFrameSectionName) : EHFrameSectionName(EHFrameSectionName) {} Error EHFrameSplitter::operator()(LinkGraph &G) { - auto *EHFrame = G.findSectionByName(EHFrameSectionName); + auto *EHFrame = G.findSectionByName(EHFrameSectionName); // .eh_frame section if (!EHFrame) { LLVM_DEBUG({ diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp index 3a270d8508152..877ce96c1738d 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp @@ -56,10 +56,10 @@ createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) { if (Buffer.size() < ELF::EI_MAG3 + 1) return make_error<JITLinkError>("Truncated ELF buffer"); - if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0) + if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0) // 校验elf的magic number return make_error<JITLinkError>("ELF magic not valid"); - Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer); + Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer); // read elf machine arch from elf file. if (!TargetMachineArch) return TargetMachineArch.takeError(); diff --git a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h index 2b2a1a8db4c1d..342683df1b9a7 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h +++ b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h @@ -137,13 +137,13 @@ ELFLinkGraphBuilder<ELFT>::ELFLinkGraphBuilder( template <typename ELFT> Expected<std::unique_ptr<LinkGraph>> ELFLinkGraphBuilder<ELFT>::buildGraph() { - if (!isRelocatable()) + if (!isRelocatable()) // 必须是可重定位的文件。 return make_error<JITLinkError>("Object is not a relocatable ELF file"); - if (auto Err = prepare()) + if (auto Err = prepare()) // 读取一些特定的section (string & symtab) return std::move(Err); - if (auto Err = graphifySections()) + if (auto Err = graphifySections()) // 为每个感兴趣的section建立graph return std::move(Err); if (auto Err = graphifySymbols()) @@ -207,14 +207,14 @@ template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::prepare() { return SectionsOrErr.takeError(); // Get the section string table. - if (auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections)) + if (auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections)) // 读取string表 SectionStringTab = *SectionStringTabOrErr; else return SectionStringTabOrErr.takeError(); // Get the SHT_SYMTAB section. for (auto &Sec : Sections) - if (Sec.sh_type == ELF::SHT_SYMTAB) { + if (Sec.sh_type == ELF::SHT_SYMTAB) { // 读取符号表 if (!SymTabSec) SymTabSec = &Sec; else @@ -397,7 +397,7 @@ template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() { *Name = GraphSec->getName(); auto &GSym = - G->addDefinedSymbol(*B, Sym.getValue(), *Name, Sym.st_size, L, S, + G->addDefinedSymbol(*B, Sym.getValue(), *Name, Sym.st_size, L, S, // ????? Sym.getType() == ELF::STT_FUNC, false); setGraphSymbol(SymIndex, GSym); } diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp index a5aed6d252007..f02255c2e920a 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp @@ -153,7 +153,7 @@ static Error optimizeELF_x86_64_GOTAndStubs(LinkGraph &G) { for (auto &E : B->edges()) if (E.getKind() == PCRel32GOTLoad) { // Replace GOT load with LEA only for MOVQ instructions. - constexpr uint8_t MOVQRIPRel[] = {0x48, 0x8b}; + constexpr uint8_t MOVQRIPRel[] = {0x48, 0x8b}; // movq ${reg1}, qword ptr [${reg2}] if (E.getOffset() < 3 || strncmp(B->getContent().data() + E.getOffset() - 3, reinterpret_cast<const char *>(MOVQRIPRel), 2) != 0) @@ -165,11 +165,11 @@ static Error optimizeELF_x86_64_GOTAndStubs(LinkGraph &G) { assert(GOTBlock.edges_size() == 1 && "GOT entry should only have one outgoing edge"); - auto &GOTTarget = GOTBlock.edges().begin()->getTarget(); + auto &GOTTarget = GOTBlock.edges().begin()->getTarget(); // GOTTarget: 当前所依赖的符号 JITTargetAddress EdgeAddr = B->getAddress() + E.getOffset(); - JITTargetAddress TargetAddr = GOTTarget.getAddress(); + JITTargetAddress TargetAddr = GOTTarget.getAddress(); // 当前符号的地址 - int64_t Displacement = TargetAddr - EdgeAddr + 4; + int64_t Displacement = TargetAddr - EdgeAddr + 4; // 当前符号和目标符号之前的间隔????? if (Displacement >= std::numeric_limits<int32_t>::min() && Displacement <= std::numeric_limits<int32_t>::max()) { // Change the edge kind as we don't go through GOT anymore. This is @@ -186,8 +186,8 @@ static Error optimizeELF_x86_64_GOTAndStubs(LinkGraph &G) { dbgs() << "\n"; }); } - } else if (E.getKind() == Branch32ToStub) { - auto &StubBlock = E.getTarget().getBlock(); + } else if (E.getKind() == Branch32ToStub) { // Branch32ToStub ---> means jump to PLT + auto &StubBlock = E.getTarget().getBlock(); // 当前PLT代码所在的Block assert( StubBlock.getSize() == sizeof(PerGraphGOTAndPLTStubsBuilder_ELF_x86_64::StubContent) && @@ -512,7 +512,7 @@ createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer) { << ObjectBuffer.getBufferIdentifier() << "...\n"; }); - auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer); + auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer); // create elf object from memory buffer if (!ELFObj) return ELFObj.takeError(); @@ -544,6 +544,8 @@ void link_ELF_x86_64(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx) { PassConfiguration Config; + G->dump(errs()); + if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) { Config.PrePrunePasses.push_back(EHFrameSplitter(".eh_frame")); diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp index 5b163ab6316dc..d935410c4ac5c 100644 --- a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp @@ -37,7 +37,7 @@ void JITLinkerBase::linkPhase1(std::unique_ptr<JITLinkerBase> Self) { G->dump(dbgs()); }); - prune(*G); + prune(*G); // 删除一些dead的符号。 LLVM_DEBUG({ dbgs() << "Link graph \"" << G->getName() << "\" post-pruning:\n"; @@ -146,7 +146,7 @@ void JITLinkerBase::linkPhase2(std::unique_ptr<JITLinkerBase> Self, }); // Fix up block content. - if (auto Err = fixUpBlocks(*G)) + if (auto Err = fixUpBlocks(*G)) // 将.text和.text.rela合并 return deallocateAndBailOut(std::move(Err)); LLVM_DEBUG({ @@ -199,7 +199,8 @@ JITLinkerBase::SegmentLayoutMap JITLinkerBase::layOutBlocks() { else SegLists.ZeroFillBlocks.push_back(B); } - + // 按照内存页面的权限信息, 对其进行分类排序。 + // 尽可能将权限一样的页面放置在一起 /// Sort blocks within each list. for (auto &KV : Layout) { diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp index f6ebfc318bfd9..7bd8102ff7317 100644 --- a/llvm/lib/ExecutionEngine/Orc/Core.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp @@ -1595,12 +1595,12 @@ Error JITDylib::defineImpl(MaterializationUnit &MU) { if (KV.second.isStrong()) { if (I->second.getFlags().isStrong() || I->second.getState() > SymbolState::NeverSearched) - Duplicates.insert(KV.first); + Duplicates.insert(KV.first); // 存在重复定义符号的问题。 else { assert(I->second.getState() == SymbolState::NeverSearched && "Overridden existing def should be in the never-searched " "state"); - ExistingDefsOverridden.push_back(KV.first); + ExistingDefsOverridden.push_back(KV.first); // 存在符号的override } } else MUDefsOverridden.push_back(KV.first); @@ -1608,7 +1608,7 @@ Error JITDylib::defineImpl(MaterializationUnit &MU) { } // If there were any duplicate definitions then bail out. - if (!Duplicates.empty()) { + if (!Duplicates.empty()) { // 不允许存在重复的符号。 LLVM_DEBUG( { dbgs() << " Error: Duplicate symbols " << Duplicates << "\n"; }); return make_error<DuplicateDefinition>(std::string(**Duplicates.begin())); @@ -1660,7 +1660,7 @@ void JITDylib::installMaterializationUnit( auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU), &RT); for (auto &KV : UMI->MU->getSymbols()) - UnmaterializedInfos[KV.first] = UMI; + UnmaterializedInfos[KV.first] = UMI; // 存储一个没有物化的映射问题: symbol -> UnmaterializedInfo } void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q, @@ -1912,16 +1912,16 @@ void ExecutionSession::lookup( // lookup can be re-entered recursively if running on a single thread. Run any // outstanding MUs in case this query depends on them, otherwise this lookup // will starve waiting for a result from an MU that is stuck in the queue. - dispatchOutstandingMUs(); + dispatchOutstandingMUs(); // 首先解析当前符号依赖的其他的符号, 这一步是同步的, 不是异步 auto Unresolved = std::move(Symbols); auto Q = std::make_shared<AsynchronousSymbolQuery>(Unresolved, RequiredState, - std::move(NotifyComplete)); + std::move(NotifyComplete)); // 用于用户查询符号, 该结构体通过回调函数来返回结果 - auto IPLS = std::make_unique<InProgressFullLookupState>( + auto IPLS = std::make_unique<InProgressFullLookupState>( // 定义了当前的查找状态。 K, SearchOrder, std::move(Unresolved), RequiredState, std::move(Q), std::move(RegisterDependencies)); - + // 当前函数触发了符号定义 OL_applyQueryPhase1(std::move(IPLS), Error::success()); } @@ -2114,6 +2114,7 @@ Error ExecutionSession::IL_updateCandidatesFor( if (SymI == JD.Symbols.end()) return false; + // 如果我们只关心那些可导出符号, 那么将那些不可导出符号添加到NonCandidates中。 // If this is a non-exported symbol and we're matching exported // symbols only then remove this symbol from the candidates list. // @@ -2122,7 +2123,7 @@ Error ExecutionSession::IL_updateCandidatesFor( if (!SymI->second.getFlags().isExported() && JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) { if (NonCandidates) - NonCandidates->add(Name, SymLookupFlags); + NonCandidates->add(Name, SymLookupFlags); // 将一些不满足的符号添加到NonCandidates中 return true; } @@ -2131,6 +2132,9 @@ Error ExecutionSession::IL_updateCandidatesFor( // an error. // FIXME: Use a "materialization-side-effects-only symbols must be // weakly referenced" specific error here to reduce confusion. + // + // 如果一个符号被标记为MaterializationSideEffectsOnly, 并且查找方式不是WeaklyReferencedSymbol, + // 那么直接抛异常。 if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() && SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol) return make_error<SymbolsNotFound>(SymbolNameVector({Name})); @@ -2168,7 +2172,7 @@ void ExecutionSession::OL_applyQueryPhase1( // single pass in the common case where all symbols have already reached the // required state. The query could be detached again in the 'fail' method on // IPLS. Phase 2 would be reduced to collecting and dispatching the MUs. - + // 根据外围定义的JTILib顺序, 依次做解析。 while (IPLS->CurSearchOrderIndex != IPLS->SearchOrder.size()) { // If we've been handed an error or received one back from a generator then @@ -2179,8 +2183,8 @@ void ExecutionSession::OL_applyQueryPhase1( // Get the next JITDylib and lookup flags. auto &KV = IPLS->SearchOrder[IPLS->CurSearchOrderIndex]; - auto &JD = *KV.first; - auto JDLookupFlags = KV.second; + auto &JD = *KV.first; // JITDylib * ----> 当前正在查找的JIT动态库 + auto JDLookupFlags = KV.second; // JITDylibLookupFlags ----> 定义了如何查找当前的JIT动态库 LLVM_DEBUG({ dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags @@ -2191,28 +2195,34 @@ void ExecutionSession::OL_applyQueryPhase1( if (IPLS->NewJITDylib) { // Acquire the generator lock for this JITDylib. - IPLS->GeneratorLock = std::unique_lock<std::mutex>(JD.GeneratorsMutex); + IPLS->GeneratorLock = std::unique_lock<std::mutex>(JD.GeneratorsMutex); // 首先持有一个来自JITLib的锁 // Add any non-candidates from the last JITDylib (if any) back on to the // list of definition candidates for this JITDylib, reset definition // non-candiates to the empty set. SymbolLookupSet Tmp; std::swap(IPLS->DefGeneratorNonCandidates, Tmp); + // 如果上一个dylib中存在没有解析完全的符号, 那么将这些符号重新加入到当前的IPLS的DefGeneratorCandidates中 + // 本轮会负责解析这些符号 IPLS->DefGeneratorCandidates.append(std::move(Tmp)); LLVM_DEBUG({ dbgs() << " First time visiting " << JD.getName() << ", resetting candidate sets and building generator stack\n"; }); - + // 如果当前的JITLib中存在过个DefGenerators // Build the definition generator stack for this JITDylib. for (auto &DG : reverse(JD.DefGenerators)) - IPLS->CurDefGeneratorStack.push_back(DG); + IPLS->CurDefGeneratorStack.push_back(DG); // #反向存储# 当前jitdylib中存在的generator // Flag that we've done our initialization. - IPLS->NewJITDylib = false; + IPLS->NewJITDylib = false; // 将当前的jitdylin标记为false, 代表已经访问过。 } + // 如果当前某一个存在于Candidates中的符号,被证明同样出现在了JITlib中, + // 那么将这个符号从DefGeneratorCandidates中删除。 + // 因此函数IL_updateCandidatesFor的作用就是删除已经解析过的符号。 + // // Remove any generation candidates that are already defined (and match) in // this JITDylib. runSessionLocked([&] { @@ -2228,6 +2238,7 @@ void ExecutionSession::OL_applyQueryPhase1( << "\n"; }); }); + // 走到这里, 理论上将, JIT会负责解析所有在Candidates中的符号。 // If we encountered an error while filtering generation candidates then // bail out. @@ -2365,12 +2376,14 @@ void ExecutionSession::OL_completeLookup( /// Search for the symbol. If not found then continue without /// removal. + /// 如果当前Dylib中没有定义对应的符号, 那么直接跳过。 auto SymI = JD.Symbols.find(Name); if (SymI == JD.Symbols.end()) { LLVM_DEBUG(dbgs() << "skipping: not present\n"); return false; } + // 只处理那些可以被导出的符号。 // If this is a non-exported symbol and we're matching exported // symbols only then skip this symbol without removal. if (!SymI->second.getFlags().isExported() && @@ -2421,11 +2434,11 @@ void ExecutionSession::OL_completeLookup( if (SymI->second.hasMaterializerAttached()) { assert(SymI->second.getAddress() == 0 && "Symbol not resolved but already has address?"); - auto UMII = JD.UnmaterializedInfos.find(Name); + auto UMII = JD.UnmaterializedInfos.find(Name); // using UnmaterializedInfosMap = DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>; assert(UMII != JD.UnmaterializedInfos.end() && "Lazy symbol should have UnmaterializedInfo"); - auto UMI = UMII->second; + auto UMI = UMII->second; // std::shared_ptr<UnmaterializedInfo> assert(UMI->MU && "Materializer should not be null"); assert(UMI->RT && "Tracker should not be null"); LLVM_DEBUG({ @@ -2434,34 +2447,34 @@ void ExecutionSession::OL_completeLookup( }); // Move all symbols associated with this MaterializationUnit into - // materializing state. + // materializing state. 将所有和该MU相关的符号状态都变成Materializing, 代表当前JIT编译器准备物化当前的符号。 for (auto &KV : UMI->MU->getSymbols()) { auto SymK = JD.Symbols.find(KV.first); assert(SymK != JD.Symbols.end() && "No entry for symbol covered by MaterializationUnit"); SymK->second.setMaterializerAttached(false); - SymK->second.setState(SymbolState::Materializing); + SymK->second.setState(SymbolState::Materializing); // 当前正在物化。 JD.UnmaterializedInfos.erase(KV.first); } // Add MU to the list of MaterializationUnits to be materialized. - CollectedUMIs[&JD].push_back(std::move(UMI)); + CollectedUMIs[&JD].push_back(std::move(UMI)); // 将当前的MU添加到CollectedUMIs中, 代表下一步就准备物化这批符号。 } else - LLVM_DEBUG(dbgs() << "matched, registering query"); + LLVM_DEBUG(dbgs() << "matched, registering query"); // 代表当前符号已经物化成功。 // Add the query to the PendingQueries list and continue, deleting // the element from the lookup set. - assert(SymI->second.getState() != SymbolState::NeverSearched && + assert(SymI->second.getState() != SymbolState::NeverSearched && // 这个判断应该是符号状态应该介于NeverSearched和ready之间 SymI->second.getState() != SymbolState::Ready && "By this line the symbol should be materializing"); auto &MI = JD.MaterializingInfos[Name]; - MI.addQuery(Q); - Q->addQueryDependence(JD, Name); + MI.addQuery(Q); // 将当前的请求串加入到MI中 + Q->addQueryDependence(JD, Name); // 将当前的符号名字加入到JD的符号列表中。 return true; }); - - // Handle failure. + // error handing: 做一些基本的出错处理。 + // Handle failure. if (Err) { LLVM_DEBUG({ @@ -2515,7 +2528,7 @@ void ExecutionSession::OL_completeLookup( dbgs() << "Query successfully " << (QueryComplete ? "completed" : "lodged") << "\n"; }); - + // 将希望物化的MU放到OutstandingMUs中。 // Move the collected MUs to the OutstandingMUs list. if (!CollectedUMIs.empty()) { std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex); @@ -2561,7 +2574,7 @@ void ExecutionSession::OL_completeLookup( Q->handleComplete(*this); } - dispatchOutstandingMUs(); + dispatchOutstandingMUs(); // 将当前的MU分配到各个工作队列中。 } void ExecutionSession::OL_completeLookupFlags( diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp index 6a1a41a13a1be..150f27f386441 100644 --- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp @@ -255,7 +255,7 @@ Error DynamicLibrarySearchGenerator::tryToGenerate( std::string Tmp((*Name).data() + HasGlobalPrefix, (*Name).size() - HasGlobalPrefix); - if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) { + if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) { // 在当前dylib中查找对应的函数地址 NewSymbols[Name] = JITEvaluatedSymbol( static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Addr)), JITSymbolFlags::Exported); diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp index 08fd86b7979b1..d61900257bb11 100644 --- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp +++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp @@ -1100,26 +1100,26 @@ LLJIT::LLJIT(LLJITBuilderState &S, Error &Err) return; } - auto ObjLayer = createObjectLinkingLayer(S, *ES); + auto ObjLayer = createObjectLinkingLayer(S, *ES); // 创建Object linker if (!ObjLayer) { Err = ObjLayer.takeError(); return; } ObjLinkingLayer = std::move(*ObjLayer); ObjTransformLayer = - std::make_unique<ObjectTransformLayer>(*ES, *ObjLinkingLayer); + std::make_unique<ObjectTransformLayer>(*ES, *ObjLinkingLayer); // ObjTransformLayer ---> RTDyldObjectLinkingLayer { - auto CompileFunction = createCompileFunction(S, std::move(*S.JTMB)); + auto CompileFunction = createCompileFunction(S, std::move(*S.JTMB)); // IRCompileLayer::IRCompiler if (!CompileFunction) { Err = CompileFunction.takeError(); return; } CompileLayer = std::make_unique<IRCompileLayer>( - *ES, *ObjTransformLayer, std::move(*CompileFunction)); + *ES, *ObjTransformLayer, std::move(*CompileFunction)); // IRCompileLayer ---> ObjTransformLayer TransformLayer = std::make_unique<IRTransformLayer>(*ES, *CompileLayer); InitHelperTransformLayer = - std::make_unique<IRTransformLayer>(*ES, *TransformLayer); + std::make_unique<IRTransformLayer>(*ES, *TransformLayer); // IRTransformLayer ----> IRCompileLayer } if (S.NumCompileThreads > 0) { diff --git a/llvm/lib/ExecutionEngine/Orc/Layer.cpp b/llvm/lib/ExecutionEngine/Orc/Layer.cpp index 20dfba23bf10e..4770934e0044c 100644 --- a/llvm/lib/ExecutionEngine/Orc/Layer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Layer.cpp @@ -25,7 +25,7 @@ IRLayer::~IRLayer() {} Error IRLayer::add(ResourceTrackerSP RT, ThreadSafeModule TSM) { assert(RT && "RT can not be null"); auto &JD = RT->getJITDylib(); - return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>( + return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>( // 在添加IRLayer的时候, 会顺带添加上BasicIRLayerMaterializationUnit, MU会负责调用对应的Layer初始化符号 *this, *getManglingOptions(), std::move(TSM)), std::move(RT)); } diff --git a/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp b/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp index e1f494415e86b..b5223dbbe029e 100644 --- a/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp +++ b/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp @@ -102,7 +102,7 @@ void LazyCallThroughManager::resolveTrampolineLandingAddress( NoDependenciesToRegister); } -Expected<std::unique_ptr<LazyCallThroughManager>> +Expected<std::unique_ptr<LazyCallThroughManager>> // Symbols --> (Symbol, Flags) createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr) { switch (T.getArch()) { _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits