[llvm-branch-commits] [llvm] 26c2169 - add some comment for jit component

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Jul 28 19:19:53 PDT 2021


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()) {


        


More information about the llvm-branch-commits mailing list