[llvm-branch-commits] [llvm] 26c2169 - add some comment for jit component
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Jul 13 03:25:32 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