diff --git a/include/CppInterOp/CppInterOp.h b/include/CppInterOp/CppInterOp.h index 0fdcc609a..4117328dd 100644 --- a/include/CppInterOp/CppInterOp.h +++ b/include/CppInterOp/CppInterOp.h @@ -328,6 +328,9 @@ CPPINTEROP_API std::string GetVersion(); ///\returns the demangled representation of the given mangled_name CPPINTEROP_API std::string Demangle(const std::string& mangled_name); +///\returns the mangled representation of the given scope +CPPINTEROP_API std::string MangledNameOf(TCppScope_t scope); + /// Enables or disables the debugging printouts on stderr. /// Debugging output can be enabled also by the environment variable /// CPPINTEROP_EXTRA_INTERPRETER_ARGS. For example, @@ -353,6 +356,9 @@ CPPINTEROP_API bool IsClass(TCppScope_t scope); /// Checks if the scope is a function. CPPINTEROP_API bool IsFunction(TCppScope_t scope); +/// Checks if the scope is an inline function. +CPPINTEROP_API bool IsInlineFunction(TCppScope_t scope); + /// Checks if the type is a function pointer. CPPINTEROP_API bool IsFunctionPointerType(TCppType_t type); @@ -622,6 +628,10 @@ CPPINTEROP_API bool IsStaticMethod(TCppConstFunction_t method); /// Checks if the provided constructor or conversion operator is explicit CPPINTEROP_API bool IsExplicit(TCppConstFunction_t method); +/// Gets the LLVM module (IR) for the given scope +CPPINTEROP_API std::string GetLLVMMouleFor(TCppScope_t scope, + TInterp_t Interp = nullptr); + ///\returns the address of the function given its potentially mangled name. CPPINTEROP_API TCppFuncAddr_t GetFunctionAddress(const char* mangled_name); diff --git a/include/CppInterOp/Dispatch.h b/include/CppInterOp/Dispatch.h index 903fd7b84..cf0ed91ff 100644 --- a/include/CppInterOp/Dispatch.h +++ b/include/CppInterOp/Dispatch.h @@ -84,6 +84,8 @@ extern "C" CPPINTEROP_API CppFnPtrTy CppGetProcAddress(const char* procname); DISPATCH_API(GetClassTemplateInstantiationArgs, \ decltype(&CppImpl::GetClassTemplateInstantiationArgs)) \ DISPATCH_API(IsClass, decltype(&CppImpl::IsClass)) \ + DISPATCH_API(IsInlineFunction, decltype(&CppImpl::IsInlineFunction)) \ + DISPATCH_API(MangledNameOf, decltype(&CppImpl::MangledNameOf)) \ DISPATCH_API(GetType, decltype(&CppImpl::GetType)) \ DISPATCH_API(GetTypeFromScope, decltype(&CppImpl::GetTypeFromScope)) \ DISPATCH_API(GetComplexType, decltype(&CppImpl::GetComplexType)) \ @@ -185,6 +187,7 @@ extern "C" CPPINTEROP_API CppFnPtrTy CppGetProcAddress(const char* procname); decltype(&CppImpl::BeginStdStreamCapture)) \ DISPATCH_API(GetDoxygenComment, decltype(&CppImpl::GetDoxygenComment)) \ DISPATCH_API(IsExplicit, decltype(&CppImpl::IsExplicit)) \ + DISPATCH_API(GetLLVMMouleFor, decltype(&CppImpl::GetLLVMMouleFor)) \ DISPATCH_API(MakeFunctionCallable, \ CppImpl::JitCall (*)(CppImpl::TCppConstFunction_t)) \ DISPATCH_API(GetFunctionAddress, \ diff --git a/lib/CppInterOp/CppInterOp.cpp b/lib/CppInterOp/CppInterOp.cpp index 9c6f00432..1314b83ca 100644 --- a/lib/CppInterOp/CppInterOp.cpp +++ b/lib/CppInterOp/CppInterOp.cpp @@ -176,6 +176,27 @@ static compat::Interpreter& getInterp(TInterp_t I = nullptr) { static clang::Sema& getSema() { return getInterp().getCI()->getSema(); } static clang::ASTContext& getASTContext() { return getSema().getASTContext(); } +std::string GetLLVMMouleFor(TCppScope_t scope, TInterp_t Interp) { + auto* D = static_cast(scope); + auto& I = getInterp(Interp); + + ASTContext& C = I.getSema().getASTContext(); + + D->addAttr(UsedAttr::CreateImplicit(C)); + I.getCI()->getASTConsumer().HandleTopLevelDecl(DeclGroupRef(D)); + + // FIXME: We parse and create a PTU but don't send it to JIT. Is this safe? + auto GeneratedPTU = I.Parse(""); + if (!GeneratedPTU) + return ""; + + std::string ModuleCode; + llvm::raw_string_ostream OS(ModuleCode); + GeneratedPTU->TheModule->print(OS, nullptr); + OS.flush(); + return ModuleCode; +} + static void ForceCodeGen(Decl* D, compat::Interpreter& I) { // The decl was deferred by CodeGen. Force its emission. // FIXME: In ASTContext::DeclMustBeEmitted we should check if the @@ -352,6 +373,12 @@ bool IsFunction(TCppScope_t scope) { return isa(D); } +bool IsInlineFunction(TCppScope_t scope) { + Decl* D = static_cast(scope); + return isa(D) && + llvm::dyn_cast(D)->isInlineSpecified(); +} + bool IsFunctionPointerType(TCppType_t type) { QualType QT = QualType::getFromOpaquePtr(type); return QT->isFunctionPointerType(); @@ -1427,6 +1454,20 @@ TCppFuncAddr_t GetFunctionAddress(const char* mangled_name) { return nullptr; } +std::string MangledNameOf(TCppScope_t scope) { + auto* D = static_cast(scope); + if (auto* FD = llvm::dyn_cast_or_null(D)) { + auto* MangleCtxt = getASTContext().createMangleContext(); + std::string mangled_name; + llvm::raw_string_ostream ostream(mangled_name); + MangleCtxt->mangleName(FD, ostream); + ostream.flush(); + delete MangleCtxt; + return mangled_name; + } + return ""; +} + static TCppFuncAddr_t GetFunctionAddress(const FunctionDecl* FD) { const auto get_mangled_name = [](const FunctionDecl* FD) { auto MangleCtxt = getASTContext().createMangleContext();