Index: clang/include/clang/Interpreter/Interpreter.h =================================================================== --- clang/include/clang/Interpreter/Interpreter.h +++ clang/include/clang/Interpreter/Interpreter.h @@ -67,7 +67,7 @@ return llvm::Error::success(); } llvm::Expected - getSymbolAddress(llvm::StringRef UnmangledName) const; + getSymbolAddress(llvm::StringRef Name, bool IsMangled = false) const; }; } // namespace clang Index: clang/lib/Interpreter/IncrementalExecutor.h =================================================================== --- clang/lib/Interpreter/IncrementalExecutor.h +++ clang/lib/Interpreter/IncrementalExecutor.h @@ -42,7 +42,7 @@ llvm::Error addModule(std::unique_ptr M); llvm::Error runCtors() const; llvm::Expected - getSymbolAddress(llvm::StringRef UnmangledName) const; + getSymbolAddress(llvm::StringRef Name, bool IsMangled = false) const; }; } // end namespace clang Index: clang/lib/Interpreter/IncrementalExecutor.cpp =================================================================== --- clang/lib/Interpreter/IncrementalExecutor.cpp +++ clang/lib/Interpreter/IncrementalExecutor.cpp @@ -61,8 +61,15 @@ } llvm::Expected -IncrementalExecutor::getSymbolAddress(llvm::StringRef UnmangledName) const { - auto Sym = Jit->lookup(UnmangledName); +IncrementalExecutor::getSymbolAddress(llvm::StringRef Name, + bool IsMangled /*=false*/) const { + if (IsMangled) { + auto Sym = Jit->lookupLinkerMangled(Name); + if (!Sym) + return Sym.takeError(); + return Sym->getAddress(); + } + auto Sym = Jit->lookup(Name); if (!Sym) return Sym.takeError(); return Sym->getAddress(); Index: clang/lib/Interpreter/Interpreter.cpp =================================================================== --- clang/lib/Interpreter/Interpreter.cpp +++ clang/lib/Interpreter/Interpreter.cpp @@ -223,11 +223,12 @@ } llvm::Expected -Interpreter::getSymbolAddress(llvm::StringRef UnmangledName) const { +Interpreter::getSymbolAddress(llvm::StringRef Name, + bool IsMangled /*=false*/) const { if (!IncrExecutor) return llvm::make_error("Operation failed. " "No execution engine", std::error_code()); - return IncrExecutor->getSymbolAddress(UnmangledName); + return IncrExecutor->getSymbolAddress(Name, IsMangled); } Index: clang/unittests/Interpreter/CMakeLists.txt =================================================================== --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} Core ) @@ -11,6 +12,7 @@ clangBasic clangInterpreter clangFrontend + clangSema ) # Exceptions on Windows are not yet supported. Index: clang/unittests/Interpreter/IncrementalProcessingTest.cpp =================================================================== --- clang/unittests/Interpreter/IncrementalProcessingTest.cpp +++ clang/unittests/Interpreter/IncrementalProcessingTest.cpp @@ -15,7 +15,9 @@ #include "clang/Interpreter/Interpreter.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/Parser.h" +#include "clang/Sema/Lookup.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/Triple.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" Index: clang/unittests/Interpreter/InterpreterTest.cpp =================================================================== --- clang/unittests/Interpreter/InterpreterTest.cpp +++ clang/unittests/Interpreter/InterpreterTest.cpp @@ -14,8 +14,13 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclGroup.h" +#include "clang/AST/Mangle.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Sema.h" + +#include "llvm/Support/TargetSelect.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -123,4 +128,109 @@ EXPECT_EQ("Parsing failed.", llvm::toString(std::move(Err))); } +static std::string MangleName(NamedDecl *ND) { + ASTContext &C = ND->getASTContext(); + std::unique_ptr MangleC(C.createMangleContext()); + std::string mangledName; + llvm::raw_string_ostream RawStr(mangledName); + MangleC->mangleName(ND, RawStr); + return RawStr.str(); +} +struct LLVMInitRAII { + LLVMInitRAII() { + llvm::InitializeNativeTarget(); + llvm::InitializeNativeTargetAsmPrinter(); + } + ~LLVMInitRAII() { llvm::llvm_shutdown(); } +} LLVMInit; + +TEST(IncrementalProcessing, FindMangledNameSymbol) { + + std::unique_ptr Interp = createInterpreter(); + + auto &PTU(cantFail(Interp->Parse("int f(const char*) {return 0;}"))); + EXPECT_EQ(1U, DeclsSize(PTU.TUPart)); + auto R1DeclRange = PTU.TUPart->decls(); + + NamedDecl *ND = cast(*R1DeclRange.begin()); + // Lower the PTU + if (llvm::Error Err = Interp->Execute(PTU)) { + // We cannot execute on the platform. + consumeError(std::move(Err)); + return; + } + + std::string MangledName = MangleName(ND); + auto Addr = + cantFail(Interp->getSymbolAddress(MangledName, /*IsMangled=*/true)); + EXPECT_TRUE(Addr != 0); +} + +static void *AllocateObject(TypeDecl *TD, Interpreter &Interp) { + std::string Name = TD->getQualifiedNameAsString(); + const clang::Type *RDTy = TD->getTypeForDecl(); + clang::ASTContext &C = Interp.getCompilerInstance()->getASTContext(); + size_t size = C.getTypeSize(RDTy); + void *loc = malloc(size); + + // Tell the interpreter to call the default ctor with this memory. Synthesize: + // new (loc) ClassName; + static unsigned counter = 0; + std::stringstream ss; + ss << "auto _v" << counter++ << " = " + << "new ((void*)" << loc << ")" << Name << "();"; + + auto R = Interp.ParseAndExecute(ss.str()); + if (!R) + return nullptr; + + return loc; +} + +static NamedDecl *LookupSingleName(Interpreter &Interp, const char *Name) { + Sema &SemaRef = Interp.getCompilerInstance()->getSema(); + ASTContext &C = SemaRef.getASTContext(); + DeclarationName DeclName = &C.Idents.get(Name); + LookupResult R(SemaRef, DeclName, SourceLocation(), Sema::LookupOrdinaryName); + SemaRef.LookupName(R, SemaRef.TUScope); + assert(!R.empty()); + return R.getFoundDecl(); +} + +TEST(IncrementalProcessing, InstantiateTemplate) { + std::unique_ptr Interp = createInterpreter(); + + llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);" + "extern \"C\" int printf(const char*,...);" + "class A {};" + "struct B {" + " template" + " int callme(T) { return 42; }" + "};")); + auto &PTU = llvm::cantFail(Interp->Parse("auto _t = &B::callme;")); + auto PTUDeclRange = PTU.TUPart->decls(); + EXPECT_TRUE(std::distance(PTUDeclRange.begin(), PTUDeclRange.end())); + + // Lower the PTU + if (llvm::Error Err = Interp->Execute(PTU)) { + // We cannot execute on the platform. + consumeError(std::move(Err)); + return; + } + + TypeDecl *TD = cast(LookupSingleName(*Interp, "A")); + void *NewA = AllocateObject(TD, *Interp); + + // Find back the template specialization + VarDecl *VD = static_cast(*PTUDeclRange.begin()); + UnaryOperator *UO = llvm::cast(VD->getInit()); + NamedDecl *TmpltSpec = llvm::cast(UO->getSubExpr())->getDecl(); + + std::string MangledName = MangleName(TmpltSpec); + typedef int (*TemplateSpecFn)(void *); + auto fn = (TemplateSpecFn)cantFail( + Interp->getSymbolAddress(MangledName, /*IsMangled=*/true)); + EXPECT_TRUE(42 == fn(NewA)); +} + } // end anonymous namespace