|
11 | 11 |
|
12 | 12 | #include "Compatibility.h"
|
13 | 13 |
|
| 14 | +#include "clang/AST/Attrs.inc" |
14 | 15 | #include "clang/AST/CXXInheritance.h"
|
15 | 16 | #include "clang/AST/Decl.h"
|
16 | 17 | #include "clang/AST/DeclAccessPair.h"
|
|
48 | 49 | #include "llvm/ADT/StringRef.h"
|
49 | 50 | #include "llvm/Demangle/Demangle.h"
|
50 | 51 | #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
|
| 52 | +#include "llvm/IR/GlobalValue.h" |
51 | 53 | #include "llvm/Support/Casting.h"
|
52 | 54 | #include "llvm/Support/CommandLine.h"
|
53 | 55 | #include "llvm/Support/Debug.h"
|
| 56 | +#include "llvm/Support/Error.h" |
54 | 57 | #include "llvm/Support/ManagedStatic.h"
|
55 | 58 | #include "llvm/Support/Path.h"
|
56 |
| -#include "llvm/Support/raw_os_ostream.h" |
| 59 | +#include "llvm/Support/raw_ostream.h" |
57 | 60 |
|
58 | 61 | #include <algorithm>
|
59 | 62 | #include <cassert>
|
|
66 | 69 | #include <sstream>
|
67 | 70 | #include <stack>
|
68 | 71 | #include <string>
|
| 72 | +#include <utility> |
69 | 73 |
|
70 | 74 | // Stream redirect.
|
71 | 75 | #ifdef _WIN32
|
@@ -136,6 +140,42 @@ static compat::Interpreter& getInterp() {
|
136 | 140 | static clang::Sema& getSema() { return getInterp().getCI()->getSema(); }
|
137 | 141 | static clang::ASTContext& getASTContext() { return getSema().getASTContext(); }
|
138 | 142 |
|
| 143 | +static void ForceCodeGen(Decl* D, compat::Interpreter& I) { |
| 144 | + // The decl was deferred by CodeGen. Force its emission. |
| 145 | + // FIXME: In ASTContext::DeclMustBeEmitted we should check if the |
| 146 | + // Decl::isUsed is set or we should be able to access CodeGen's |
| 147 | + // addCompilerUsedGlobal. |
| 148 | + ASTContext& C = I.getSema().getASTContext(); |
| 149 | + |
| 150 | + D->addAttr(UsedAttr::CreateImplicit(C)); |
| 151 | +#ifdef CPPINTEROP_USE_CLING |
| 152 | + cling::Interpreter::PushTransactionRAII RAII(&I); |
| 153 | + I.getCI()->getASTConsumer().HandleTopLevelDecl(DeclGroupRef(D)); |
| 154 | +#else // CLANG_REPL |
| 155 | + I.getCI()->getASTConsumer().HandleTopLevelDecl(DeclGroupRef(D)); |
| 156 | + // Take the newest llvm::Module produced by CodeGen and send it to JIT. |
| 157 | + auto GeneratedPTU = I.Parse(""); |
| 158 | + if (!GeneratedPTU) |
| 159 | + llvm::logAllUnhandledErrors(GeneratedPTU.takeError(), llvm::errs(), |
| 160 | + "[ForceCodeGen] Failed to generate PTU:"); |
| 161 | + |
| 162 | + // From cling's BackendPasses.cpp |
| 163 | + // FIXME: We need to upstream this code in IncrementalExecutor::addModule |
| 164 | + for (auto& GV : GeneratedPTU->TheModule->globals()) { |
| 165 | + llvm::GlobalValue::LinkageTypes LT = GV.getLinkage(); |
| 166 | + if (GV.isDeclaration() || !GV.hasName() || |
| 167 | + GV.getName().starts_with(".str") || |
| 168 | + !llvm::GlobalVariable::isDiscardableIfUnused(LT) || |
| 169 | + LT != llvm::GlobalValue::InternalLinkage) |
| 170 | + continue; // nothing to do |
| 171 | + GV.setLinkage(llvm::GlobalValue::WeakAnyLinkage); |
| 172 | + } |
| 173 | + if (auto Err = I.Execute(*GeneratedPTU)) |
| 174 | + llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), |
| 175 | + "[ForceCodeGen] Failed to execute PTU:"); |
| 176 | +#endif |
| 177 | +} |
| 178 | + |
139 | 179 | #define DEBUG_TYPE "jitcall"
|
140 | 180 | bool JitCall::AreArgumentsValid(void* result, ArgList args, void* self,
|
141 | 181 | size_t nary) const {
|
@@ -1335,8 +1375,16 @@ static TCppFuncAddr_t GetFunctionAddress(const FunctionDecl* FD) {
|
1335 | 1375 |
|
1336 | 1376 | TCppFuncAddr_t GetFunctionAddress(TCppFunction_t method) {
|
1337 | 1377 | auto* D = static_cast<Decl*>(method);
|
1338 |
| - if (auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) |
| 1378 | + if (auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) { |
| 1379 | + if ((IsTemplateInstantiationOrSpecialization(FD) || |
| 1380 | + FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization) && |
| 1381 | + !FD->getDefinition()) |
| 1382 | + InstantiateFunctionDefinition(D); |
| 1383 | + ASTContext& C = getASTContext(); |
| 1384 | + if (isDiscardableGVALinkage(C.GetGVALinkageForFunction(FD))) |
| 1385 | + ForceCodeGen(FD, getInterp()); |
1339 | 1386 | return GetFunctionAddress(FD);
|
| 1387 | + } |
1340 | 1388 | return nullptr;
|
1341 | 1389 | }
|
1342 | 1390 |
|
@@ -1554,39 +1602,8 @@ intptr_t GetVariableOffset(compat::Interpreter& I, Decl* D,
|
1554 | 1602 | }
|
1555 | 1603 | if (!address) {
|
1556 | 1604 | auto Linkage = C.GetGVALinkageForVariable(VD);
|
1557 |
| - // The decl was deferred by CodeGen. Force its emission. |
1558 |
| - // FIXME: In ASTContext::DeclMustBeEmitted we should check if the |
1559 |
| - // Decl::isUsed is set or we should be able to access CodeGen's |
1560 |
| - // addCompilerUsedGlobal. |
1561 | 1605 | if (isDiscardableGVALinkage(Linkage))
|
1562 |
| - VD->addAttr(UsedAttr::CreateImplicit(C)); |
1563 |
| -#ifdef CPPINTEROP_USE_CLING |
1564 |
| - cling::Interpreter::PushTransactionRAII RAII(&I); |
1565 |
| - I.getCI()->getASTConsumer().HandleTopLevelDecl(DeclGroupRef(VD)); |
1566 |
| -#else // CLANG_REPL |
1567 |
| - I.getCI()->getASTConsumer().HandleTopLevelDecl(DeclGroupRef(VD)); |
1568 |
| - // Take the newest llvm::Module produced by CodeGen and send it to JIT. |
1569 |
| - auto GeneratedPTU = I.Parse(""); |
1570 |
| - if (!GeneratedPTU) |
1571 |
| - llvm::logAllUnhandledErrors( |
1572 |
| - GeneratedPTU.takeError(), llvm::errs(), |
1573 |
| - "[GetVariableOffset] Failed to generate PTU:"); |
1574 |
| - |
1575 |
| - // From cling's BackendPasses.cpp |
1576 |
| - // FIXME: We need to upstream this code in IncrementalExecutor::addModule |
1577 |
| - for (auto& GV : GeneratedPTU->TheModule->globals()) { |
1578 |
| - llvm::GlobalValue::LinkageTypes LT = GV.getLinkage(); |
1579 |
| - if (GV.isDeclaration() || !GV.hasName() || |
1580 |
| - GV.getName().starts_with(".str") || !GV.isDiscardableIfUnused(LT) || |
1581 |
| - LT != llvm::GlobalValue::InternalLinkage) |
1582 |
| - continue; // nothing to do |
1583 |
| - GV.setLinkage(llvm::GlobalValue::WeakAnyLinkage); |
1584 |
| - } |
1585 |
| - if (auto Err = I.Execute(*GeneratedPTU)) |
1586 |
| - llvm::logAllUnhandledErrors( |
1587 |
| - std::move(Err), llvm::errs(), |
1588 |
| - "[GetVariableOffset] Failed to execute PTU:"); |
1589 |
| -#endif |
| 1606 | + ForceCodeGen(VD, I); |
1590 | 1607 | }
|
1591 | 1608 | auto VDAorErr = compat::getSymbolAddress(I, StringRef(mangledName));
|
1592 | 1609 | if (!VDAorErr) {
|
|
0 commit comments