diff --git a/include/CppInterOp/CppInterOpDispatch.h b/include/CppInterOp/CppInterOpDispatch.h new file mode 100644 index 000000000..20ca4c09c --- /dev/null +++ b/include/CppInterOp/CppInterOpDispatch.h @@ -0,0 +1,520 @@ +//--------------------------------------------------------------------*- C++ -*- +// CppInterOp Dispatch Mechanism +// author: Aaron Jomy +//===----------------------------------------------------------------------===// +// +// This defines the mechanism which enables dispatching of the CppInterOp API +// without linking to it, preventing any LLVM or Clang symbols from being leaked +// into the client application. +// +//===----------------------------------------------------------------------===// +#ifndef CPPINTEROP_CPPINTEROPDISPATCH_H +#define CPPINTEROP_CPPINTEROPDISPATCH_H + +#include +#include +#include +#include +#include + +#include + +using __CPP_FUNC = void (*)(); +struct FunctionEntry { + const char* name; + __CPP_FUNC address; +}; + +///\param[in] procname - the name of the FunctionEntry in the symbol lookup +/// table. +/// +///\returns the function address of the requested API, or nullptr if not found +extern "C" CPPINTEROP_API void ( + *CppGetProcAddress(const unsigned char* procname))(void); + +#define DECLARE_CPP_NULL(func_name) CppAPIType::func_name func_name = nullptr; + +#define EXTERN_CPP_FUNC(func_name) extern CppAPIType::func_name func_name; + +#define LOAD_CPP_FUNCTION(func_name) \ + func_name = \ + reinterpret_cast(dlGetProcAddress(#func_name)); + +// macro that allows declaration and loading of all CppInterOp API functions in +// a consistent way. This is used as our dispatched API list, along with the +// name-address pair table +#define FOR_EACH_CPP_FUNCTION(DO) \ + DO(CreateInterpreter) \ + DO(GetInterpreter) \ + DO(Process) \ + DO(GetResourceDir) \ + DO(AddIncludePath) \ + DO(LoadLibrary) \ + DO(Declare) \ + DO(DeleteInterpreter) \ + DO(IsNamespace) \ + DO(ObjToString) \ + DO(GetQualifiedCompleteName) \ + DO(IsLValueReferenceType) \ + DO(GetNonReferenceType) \ + DO(IsEnumType) \ + DO(GetIntegerTypeFromEnumType) \ + DO(GetReferencedType) \ + DO(IsPointerType) \ + DO(GetPointeeType) \ + DO(GetPointerType) \ + DO(IsReferenceType) \ + DO(GetTypeAsString) \ + DO(GetCanonicalType) \ + DO(HasTypeQualifier) \ + DO(RemoveTypeQualifier) \ + DO(GetUnderlyingType) \ + DO(IsRecordType) \ + DO(IsFunctionPointerType) \ + DO(GetVariableType) \ + DO(GetNamed) \ + DO(GetScopeFromType) \ + DO(GetClassTemplateInstantiationArgs) \ + DO(IsClass) \ + DO(GetType) \ + DO(GetTypeFromScope) \ + DO(GetComplexType) \ + DO(GetIntegerTypeFromEnumScope) \ + DO(GetUnderlyingScope) \ + DO(GetScope) \ + DO(GetGlobalScope) \ + DO(GetScopeFromCompleteName) \ + DO(InstantiateTemplate) \ + DO(GetParentScope) \ + DO(IsTemplate) \ + DO(IsTemplateSpecialization) \ + DO(IsTypedefed) \ + DO(IsClassPolymorphic) \ + DO(Demangle) \ + DO(SizeOf) \ + DO(GetSizeOfType) \ + DO(IsBuiltin) \ + DO(IsComplete) \ + DO(Allocate) \ + DO(Deallocate) \ + DO(Construct) \ + DO(Destruct) \ + DO(MakeFunctionCallable) \ + DO(GetFunctionAddress) \ + DO(IsAbstract) \ + DO(IsEnumScope) \ + DO(IsEnumConstant) \ + DO(IsAggregate) \ + DO(HasDefaultConstructor) \ + DO(IsVariable) \ + DO(GetAllCppNames) \ + DO(GetUsingNamespaces) \ + DO(GetCompleteName) \ + DO(GetDestructor) \ + DO(IsVirtualMethod) \ + DO(GetNumBases) \ + DO(GetName) \ + DO(GetBaseClass) \ + DO(IsSubclass) \ + DO(GetOperator) \ + DO(GetFunctionReturnType) \ + DO(GetBaseClassOffset) \ + DO(GetClassMethods) \ + DO(GetFunctionsUsingName) \ + DO(GetFunctionNumArgs) \ + DO(GetFunctionRequiredArgs) \ + DO(GetFunctionArgName) \ + DO(GetFunctionArgType) \ + DO(GetFunctionArgDefault) \ + DO(IsConstMethod) \ + DO(GetFunctionTemplatedDecls) \ + DO(ExistsFunctionTemplate) \ + DO(IsTemplatedFunction) \ + DO(IsStaticMethod) \ + DO(GetClassTemplatedMethods) \ + DO(BestOverloadFunctionMatch) \ + DO(GetOperatorFromSpelling) \ + DO(IsFunctionDeleted) \ + DO(IsPublicMethod) \ + DO(IsProtectedMethod) \ + DO(IsPrivateMethod) \ + DO(IsConstructor) \ + DO(IsDestructor) \ + DO(GetDatamembers) \ + DO(GetStaticDatamembers) \ + DO(GetEnumConstantDatamembers) \ + DO(LookupDatamember) \ + DO(IsLambdaClass) \ + DO(GetQualifiedName) \ + DO(GetVariableOffset) \ + DO(IsPublicVariable) \ + DO(IsProtectedVariable) \ + DO(IsPrivateVariable) \ + DO(IsStaticVariable) \ + DO(IsConstVariable) \ + DO(GetDimensions) \ + DO(GetEnumConstants) \ + DO(GetEnumConstantType) \ + DO(GetEnumConstantValue) \ + DO(DumpScope) \ + DO(AddSearchPath) \ + DO(Evaluate) \ + DO(IsDebugOutputEnabled) \ + DO(EnableDebugOutput) + +namespace CppDispatch { +// Forward all type aliases +using TCppIndex_t = ::Cpp::TCppIndex_t; +using TCppScope_t = ::Cpp::TCppScope_t; +using TCppConstScope_t = ::Cpp::TCppConstScope_t; +using TCppType_t = ::Cpp::TCppType_t; +using TCppFunction_t = ::Cpp::TCppFunction_t; +using TCppConstFunction_t = ::Cpp::TCppConstFunction_t; +using TCppFuncAddr_t = ::Cpp::TCppFuncAddr_t; +using TInterp_t = ::Cpp::TInterp_t; +using TCppObject_t = ::Cpp::TCppObject_t; + +using Operator = ::Cpp::Operator; +using OperatorArity = ::Cpp::OperatorArity; +using QualKind = ::Cpp::QualKind; +using TemplateArgInfo = ::Cpp::TemplateArgInfo; + +using JitCall = ::Cpp::JitCall; +} // end namespace CppDispatch + +namespace CppAPIType { + +using GetVersion = std::string (*)(); + +using Demangle = std::string (*)(const std::string& mangled_name); + +using EnableDebugOutput = void (*)(bool value); + +using IsDebugOutputEnabled = bool (*)(); + +using IsAggregate = bool (*)(Cpp::TCppScope_t scope); + +using IsNamespace = bool (*)(Cpp::TCppScope_t scope); + +using IsClass = bool (*)(Cpp::TCppScope_t scope); + +using IsFunction = bool (*)(Cpp::TCppScope_t scope); + +using IsFunctionPointerType = bool (*)(Cpp::TCppType_t type); + +using IsClassPolymorphic = bool (*)(Cpp::TCppScope_t klass); + +using IsComplete = bool (*)(Cpp::TCppScope_t scope); + +using SizeOf = size_t (*)(Cpp::TCppScope_t scope); + +using IsBuiltin = bool (*)(Cpp::TCppType_t type); + +using IsTemplate = bool (*)(Cpp::TCppScope_t handle); + +using IsTemplateSpecialization = bool (*)(Cpp::TCppScope_t handle); + +using IsTypedefed = bool (*)(Cpp::TCppScope_t handle); + +using IsAbstract = bool (*)(Cpp::TCppType_t klass); + +using IsEnumScope = bool (*)(Cpp::TCppScope_t handle); + +using IsEnumConstant = bool (*)(Cpp::TCppScope_t handle); + +using IsEnumType = bool (*)(Cpp::TCppType_t type); + +using HasTypeQualifier = bool (*)(Cpp::TCppType_t type, Cpp::QualKind qual); + +using RemoveTypeQualifier = Cpp::TCppType_t (*)(Cpp::TCppType_t type, + Cpp::QualKind qual); + +using AddTypeQualifier = Cpp::TCppType_t (*)(Cpp::TCppType_t type, + Cpp::QualKind qual); + +using GetEnums = void (*)(Cpp::TCppScope_t scope, + std::vector& Result); + +using IsSmartPtrType = bool (*)(Cpp::TCppType_t type); + +using GetIntegerTypeFromEnumScope = + Cpp::TCppType_t (*)(Cpp::TCppScope_t handle); + +using GetIntegerTypeFromEnumType = Cpp::TCppType_t (*)(Cpp::TCppType_t handle); + +using GetEnumConstants = + std::vector (*)(Cpp::TCppScope_t scope); + +using GetEnumConstantType = Cpp::TCppType_t (*)(Cpp::TCppScope_t scope); + +using GetEnumConstantValue = Cpp::TCppIndex_t (*)(Cpp::TCppScope_t scope); + +using GetSizeOfType = size_t (*)(Cpp::TCppType_t type); + +using IsVariable = bool (*)(Cpp::TCppScope_t scope); + +using GetName = std::string (*)(Cpp::TCppScope_t klass); + +using GetCompleteName = std::string (*)(Cpp::TCppScope_t klass); + +using GetQualifiedName = std::string (*)(Cpp::TCppScope_t klass); + +using GetQualifiedCompleteName = std::string (*)(Cpp::TCppScope_t klass); + +using GetUsingNamespaces = + std::vector (*)(Cpp::TCppScope_t scope); + +using GetGlobalScope = Cpp::TCppScope_t (*)(); + +using GetUnderlyingScope = Cpp::TCppScope_t (*)(Cpp::TCppScope_t scope); + +using GetScope = Cpp::TCppScope_t (*)(const std::string& name, + Cpp::TCppScope_t parent); + +using GetScopeFromCompleteName = Cpp::TCppScope_t (*)(const std::string& name); + +using GetNamed = Cpp::TCppScope_t (*)(const std::string& name, + Cpp::TCppScope_t parent); + +using GetParentScope = Cpp::TCppScope_t (*)(Cpp::TCppScope_t scope); + +using GetScopeFromType = Cpp::TCppScope_t (*)(Cpp::TCppType_t type); + +using GetNumBases = Cpp::TCppIndex_t (*)(Cpp::TCppScope_t klass); + +using GetBaseClass = Cpp::TCppScope_t (*)(Cpp::TCppScope_t klass, + Cpp::TCppIndex_t ibase); + +using IsSubclass = bool (*)(Cpp::TCppScope_t derived, Cpp::TCppScope_t base); + +using GetBaseClassOffset = int64_t (*)(Cpp::TCppScope_t derived, + Cpp::TCppScope_t base); + +using GetClassMethods = void (*)(Cpp::TCppScope_t klass, + std::vector& methods); + +using GetFunctionTemplatedDecls = + void (*)(Cpp::TCppScope_t klass, std::vector& methods); + +using HasDefaultConstructor = bool (*)(Cpp::TCppScope_t scope); + +using GetDefaultConstructor = Cpp::TCppFunction_t (*)(Cpp::TCppScope_t scope); + +using GetDestructor = Cpp::TCppFunction_t (*)(Cpp::TCppScope_t scope); + +using GetFunctionsUsingName = std::vector (*)( + Cpp::TCppScope_t scope, const std::string& name); + +using GetFunctionReturnType = Cpp::TCppType_t (*)(Cpp::TCppFunction_t func); + +using GetFunctionNumArgs = Cpp::TCppIndex_t (*)(Cpp::TCppFunction_t func); + +using GetFunctionRequiredArgs = + Cpp::TCppIndex_t (*)(Cpp::TCppConstFunction_t func); + +using GetFunctionArgType = Cpp::TCppType_t (*)(Cpp::TCppFunction_t func, + Cpp::TCppIndex_t iarg); + +using GetFunctionSignature = std::string (*)(Cpp::TCppFunction_t func); + +using IsFunctionDeleted = bool (*)(Cpp::TCppConstFunction_t function); + +using IsTemplatedFunction = bool (*)(Cpp::TCppFunction_t func); + +using ExistsFunctionTemplate = bool (*)(const std::string& name, + Cpp::TCppScope_t parent); + +using GetClassTemplatedMethods = + bool (*)(const std::string& name, Cpp::TCppScope_t parent, + std::vector& funcs); + +using IsMethod = bool (*)(Cpp::TCppConstFunction_t method); + +using IsPublicMethod = bool (*)(Cpp::TCppFunction_t method); + +using IsProtectedMethod = bool (*)(Cpp::TCppFunction_t method); + +using IsPrivateMethod = bool (*)(Cpp::TCppFunction_t method); + +using IsConstructor = bool (*)(Cpp::TCppConstFunction_t method); + +using IsDestructor = bool (*)(Cpp::TCppConstFunction_t method); + +using IsStaticMethod = bool (*)(Cpp::TCppConstFunction_t method); + +using GetFunctionAddressFromName = + Cpp::TCppFuncAddr_t (*)(const char* mangled_name); + +using GetFunctionAddressFromMethod = + Cpp::TCppFuncAddr_t (*)(Cpp::TCppFunction_t method); + +using IsVirtualMethod = bool (*)(Cpp::TCppFunction_t method); + +using GetDatamembers = void (*)(Cpp::TCppScope_t scope, + std::vector& datamembers); + +using GetStaticDatamembers = void (*)( + Cpp::TCppScope_t scope, std::vector& datamembers); + +using GetEnumConstantDatamembers = + void (*)(Cpp::TCppScope_t scope, std::vector& datamembers, + bool include_enum_class); + +using LookupDatamember = Cpp::TCppScope_t (*)(const std::string& name, + Cpp::TCppScope_t parent); + +using IsLambdaClass = bool (*)(Cpp::TCppType_t type); + +using GetVariableType = Cpp::TCppType_t (*)(Cpp::TCppScope_t var); + +using GetVariableOffset = intptr_t (*)(Cpp::TCppScope_t var, + Cpp::TCppScope_t parent); + +using IsPublicVariable = bool (*)(Cpp::TCppScope_t var); + +using IsProtectedVariable = bool (*)(Cpp::TCppScope_t var); + +using IsPrivateVariable = bool (*)(Cpp::TCppScope_t var); + +using IsStaticVariable = bool (*)(Cpp::TCppScope_t var); + +using IsConstVariable = bool (*)(Cpp::TCppScope_t var); + +using IsRecordType = bool (*)(Cpp::TCppType_t type); + +using IsPODType = bool (*)(Cpp::TCppType_t type); + +using IsPointerType = bool (*)(Cpp::TCppType_t type); + +using GetPointeeType = Cpp::TCppType_t (*)(Cpp::TCppType_t type); + +using IsReferenceType = bool (*)(Cpp::TCppType_t type); + +using IsLValueReferenceType = bool (*)(Cpp::TCppType_t type); + +using IsRValueReferenceType = bool (*)(Cpp::TCppType_t type); + +using GetPointerType = Cpp::TCppType_t (*)(Cpp::TCppType_t type); + +using GetReferencedType = Cpp::TCppType_t (*)(Cpp::TCppType_t type, + bool rvalue); + +using GetNonReferenceType = Cpp::TCppType_t (*)(Cpp::TCppType_t type); + +using GetTypeAsString = std::string (*)(Cpp::TCppType_t type); + +using GetCanonicalType = Cpp::TCppType_t (*)(Cpp::TCppType_t type); + +using JitCallMakeFunctionCallable = + Cpp::JitCall (*)(Cpp::TCppConstFunction_t func); + +using IsConstMethod = bool (*)(Cpp::TCppFunction_t method); + +using GetFunctionArgDefault = std::string (*)(Cpp::TCppFunction_t func, + Cpp::TCppIndex_t param_index); + +using GetFunctionArgName = std::string (*)(Cpp::TCppFunction_t func, + Cpp::TCppIndex_t param_index); + +using GetSpellingFromOperator = std::string (*)(Cpp::Operator op); + +using GetOperatorFromSpelling = Cpp::Operator (*)(const std::string& op); + +using GetOperatorArity = Cpp::OperatorArity (*)(Cpp::TCppFunction_t op); + +using GetOperator = void (*)(Cpp::TCppScope_t scope, Cpp::Operator op, + std::vector& operators, + Cpp::OperatorArity kind); + +using CreateInterpreter = + Cpp::TInterp_t (*)(const std::vector& Args, + const std::vector& GpuArgs); + +using DeleteInterpreter = bool (*)(Cpp::TInterp_t interp); + +using ActivateInterpreter = bool (*)(Cpp::TInterp_t interp); + +using GetInterpreter = Cpp::TInterp_t (*)(); + +using UseExternalInterpreter = void (*)(Cpp::TInterp_t interp); + +using AddSearchPath = void (*)(const char* dir, bool isUser, bool prepend); + +using GetResourceDir = const char* (*)(); + +using DetectResourceDir = std::string (*)(const char* ClangBinaryName); + +using DetectSystemCompilerIncludePaths = + void (*)(std::vector& Paths, const char* CompilerName); + +using AddIncludePath = void (*)(const char* dir); + +using GetIncludePaths = void (*)(std::vector& IncludePaths, + bool withSystem, bool withFlags); + +using Declare = int (*)(const char* code, bool silent); + +using Process = int (*)(const char* code); + +using Evaluate = intptr_t (*)(const char* code, bool* HadError); + +using LookupLibrary = std::string (*)(const char* lib_name); + +using LoadLibrary = bool (*)(const char* lib_stem, bool lookup); + +using UnloadLibrary = void (*)(const char* lib_stem); + +using SearchLibrariesForSymbol = std::string (*)(const char* mangled_name, + bool search_system); + +using InsertOrReplaceJitSymbol = bool (*)(const char* linker_mangled_name, + uint64_t address); + +using ObjToString = std::string (*)(const char* type, void* obj); + +using GetUnderlyingType = Cpp::TCppType_t (*)(Cpp::TCppType_t type); + +using BestOverloadFunctionMatch = Cpp::TCppFunction_t (*)( + const std::vector& candidates, + const std::vector& explicit_types, + const std::vector& arg_types); + +using GetDimensions = std::vector (*)(Cpp::TCppType_t var); + +using DumpScope = void (*)(Cpp::TCppScope_t scope); + +using GetClassTemplateInstantiationArgs = + void (*)(Cpp::TCppScope_t klass, std::vector& args); + +using GetAllCppNames = void (*)(Cpp::TCppScope_t scope, + std::set& names); + +using Deallocate = void (*)(Cpp::TCppScope_t scope, Cpp::TCppObject_t address, + Cpp::TCppIndex_t count); + +using Allocate = Cpp::TCppObject_t (*)(Cpp::TCppScope_t scope, + Cpp::TCppIndex_t count); + +using InstantiateTemplate = Cpp::TCppScope_t (*)( + Cpp::TCppScope_t tmpl, const Cpp::TemplateArgInfo* template_args, + size_t template_args_size, bool instantiate_body); + +using GetComplexType = Cpp::TCppType_t (*)(Cpp::TCppType_t type); + +using GetTypeFromScope = Cpp::TCppType_t (*)(Cpp::TCppScope_t klass); + +using GetType = Cpp::TCppType_t (*)(const std::string& type); + +using Construct = Cpp::TCppObject_t (*)(Cpp::TCppScope_t scope, + Cpp::TCppObject_t arena, + Cpp::TCppIndex_t count); + +using Destruct = bool (*)(Cpp::TCppObject_t This, Cpp::TCppScope_t scope, + bool withFree, Cpp::TCppIndex_t count); + +using MakeFunctionCallable = Cpp::JitCall (*)(Cpp::TCppConstFunction_t func); +using GetFunctionAddress = + Cpp::TCppFuncAddr_t (*)(Cpp::TCppConstFunction_t func); +} // end namespace CppAPIType + +#endif // CPPINTEROP_CPPINTEROPDISPATCH_H diff --git a/lib/CppInterOp/CMakeLists.txt b/lib/CppInterOp/CMakeLists.txt index 41288fb60..fec2def58 100644 --- a/lib/CppInterOp/CMakeLists.txt +++ b/lib/CppInterOp/CMakeLists.txt @@ -109,6 +109,7 @@ endif() add_llvm_library(clangCppInterOp DISABLE_LLVM_LINK_LLVM_DYLIB CppInterOp.cpp + CppInterOpDispatch.cpp CXCppInterOp.cpp ${DLM} LINK_LIBS diff --git a/lib/CppInterOp/CppInterOpDispatch.cpp b/lib/CppInterOp/CppInterOpDispatch.cpp new file mode 100644 index 000000000..40f227f16 --- /dev/null +++ b/lib/CppInterOp/CppInterOpDispatch.cpp @@ -0,0 +1,159 @@ +//------------------------------------------------------------------------------ +// CppInterOp Dispatch Implementation +// author: Aaron Jomy +//------------------------------------------------------------------------------ + +#include +#include + +#include + +static const FunctionEntry api_function_table[] = { + {"GetInterpreter", (__CPP_FUNC)Cpp::GetInterpreter}, + {"CreateInterpreter", (__CPP_FUNC)Cpp::CreateInterpreter}, + {"Process", (__CPP_FUNC)Cpp::Process}, + {"GetResourceDir", (__CPP_FUNC)Cpp::GetResourceDir}, + {"AddIncludePath", (__CPP_FUNC)Cpp::AddIncludePath}, + {"LoadLibrary", (__CPP_FUNC)Cpp::LoadLibrary}, + {"Declare", (__CPP_FUNC)Cpp::Declare}, + {"DeleteInterpreter", (__CPP_FUNC)Cpp::DeleteInterpreter}, + {"IsNamespace", (__CPP_FUNC)Cpp::IsNamespace}, + {"ObjToString", (__CPP_FUNC)Cpp::ObjToString}, + {"GetQualifiedCompleteName", (__CPP_FUNC)Cpp::GetQualifiedCompleteName}, + {"IsLValueReferenceType", (__CPP_FUNC)Cpp::IsLValueReferenceType}, + {"GetNonReferenceType", (__CPP_FUNC)Cpp::GetNonReferenceType}, + {"IsEnumType", (__CPP_FUNC)Cpp::IsEnumType}, + {"GetIntegerTypeFromEnumType", (__CPP_FUNC)Cpp::GetIntegerTypeFromEnumType}, + {"GetReferencedType", (__CPP_FUNC)Cpp::GetReferencedType}, + {"IsPointerType", (__CPP_FUNC)Cpp::IsPointerType}, + {"GetPointeeType", (__CPP_FUNC)Cpp::GetPointeeType}, + {"GetPointerType", (__CPP_FUNC)Cpp::GetPointerType}, + {"IsReferenceType", (__CPP_FUNC)Cpp::IsReferenceType}, + {"GetTypeAsString", (__CPP_FUNC)Cpp::GetTypeAsString}, + {"GetCanonicalType", (__CPP_FUNC)Cpp::GetCanonicalType}, + {"HasTypeQualifier", (__CPP_FUNC)Cpp::HasTypeQualifier}, + {"RemoveTypeQualifier", (__CPP_FUNC)Cpp::RemoveTypeQualifier}, + {"GetUnderlyingType", (__CPP_FUNC)Cpp::GetUnderlyingType}, + {"IsRecordType", (__CPP_FUNC)Cpp::IsRecordType}, + {"IsFunctionPointerType", (__CPP_FUNC)Cpp::IsFunctionPointerType}, + {"GetVariableType", (__CPP_FUNC)Cpp::GetVariableType}, + {"GetNamed", (__CPP_FUNC)Cpp::GetNamed}, + {"GetScopeFromType", (__CPP_FUNC)Cpp::GetScopeFromType}, + {"GetClassTemplateInstantiationArgs", + (__CPP_FUNC)Cpp::GetClassTemplateInstantiationArgs}, + {"IsClass", (__CPP_FUNC)Cpp::IsClass}, + {"GetType", (__CPP_FUNC)Cpp::GetType}, + {"GetTypeFromScope", (__CPP_FUNC)Cpp::GetTypeFromScope}, + {"GetComplexType", (__CPP_FUNC)Cpp::GetComplexType}, + {"GetIntegerTypeFromEnumScope", + (__CPP_FUNC)Cpp::GetIntegerTypeFromEnumScope}, + {"GetUnderlyingScope", (__CPP_FUNC)Cpp::GetUnderlyingScope}, + {"GetScope", (__CPP_FUNC)Cpp::GetScope}, + {"GetGlobalScope", (__CPP_FUNC)Cpp::GetGlobalScope}, + {"GetScopeFromCompleteName", (__CPP_FUNC)Cpp::GetScopeFromCompleteName}, + {"InstantiateTemplate", (__CPP_FUNC)Cpp::InstantiateTemplate}, + {"GetParentScope", (__CPP_FUNC)Cpp::GetParentScope}, + {"IsTemplate", (__CPP_FUNC)Cpp::IsTemplate}, + {"IsTemplateSpecialization", (__CPP_FUNC)Cpp::IsTemplateSpecialization}, + {"IsTypedefed", (__CPP_FUNC)Cpp::IsTypedefed}, + {"IsClassPolymorphic", (__CPP_FUNC)Cpp::IsClassPolymorphic}, + {"Demangle", (__CPP_FUNC)Cpp::Demangle}, + {"SizeOf", (__CPP_FUNC)Cpp::SizeOf}, + {"GetSizeOfType", (__CPP_FUNC)Cpp::GetSizeOfType}, + {"IsBuiltin", (__CPP_FUNC)Cpp::IsBuiltin}, + {"IsComplete", (__CPP_FUNC)Cpp::IsComplete}, + {"Allocate", (__CPP_FUNC)Cpp::Allocate}, + {"Deallocate", (__CPP_FUNC)Cpp::Deallocate}, + {"Construct", (__CPP_FUNC)Cpp::Construct}, + {"Destruct", (__CPP_FUNC)Cpp::Destruct}, + {"MakeFunctionCallable", + (__CPP_FUNC) static_cast( + &Cpp::MakeFunctionCallable)}, + {"GetFunctionAddress", + (__CPP_FUNC) static_cast( + &Cpp::GetFunctionAddress)}, + {"IsAbstract", (__CPP_FUNC)Cpp::IsAbstract}, + {"IsEnumScope", (__CPP_FUNC)Cpp::IsEnumScope}, + {"IsEnumConstant", (__CPP_FUNC)Cpp::IsEnumConstant}, + {"IsAggregate", (__CPP_FUNC)Cpp::IsAggregate}, + {"HasDefaultConstructor", (__CPP_FUNC)Cpp::HasDefaultConstructor}, + {"IsVariable", (__CPP_FUNC)Cpp::IsVariable}, + {"GetAllCppNames", (__CPP_FUNC)Cpp::GetAllCppNames}, + {"GetUsingNamespaces", (__CPP_FUNC)Cpp::GetUsingNamespaces}, + {"GetCompleteName", (__CPP_FUNC)Cpp::GetCompleteName}, + {"GetDestructor", (__CPP_FUNC)Cpp::GetDestructor}, + {"IsVirtualMethod", (__CPP_FUNC)Cpp::IsVirtualMethod}, + {"GetNumBases", (__CPP_FUNC)Cpp::GetNumBases}, + {"GetName", (__CPP_FUNC)Cpp::GetName}, + {"GetBaseClass", (__CPP_FUNC)Cpp::GetBaseClass}, + {"IsSubclass", (__CPP_FUNC)Cpp::IsSubclass}, + {"GetOperator", (__CPP_FUNC)Cpp::GetOperator}, + {"GetFunctionReturnType", (__CPP_FUNC)Cpp::GetFunctionReturnType}, + {"GetBaseClassOffset", (__CPP_FUNC)Cpp::GetBaseClassOffset}, + {"GetClassMethods", (__CPP_FUNC)Cpp::GetClassMethods}, + {"GetFunctionsUsingName", (__CPP_FUNC)Cpp::GetFunctionsUsingName}, + {"GetFunctionNumArgs", (__CPP_FUNC)Cpp::GetFunctionNumArgs}, + {"GetFunctionRequiredArgs", (__CPP_FUNC)Cpp::GetFunctionRequiredArgs}, + {"GetFunctionArgName", (__CPP_FUNC)Cpp::GetFunctionArgName}, + {"GetFunctionArgType", (__CPP_FUNC)Cpp::GetFunctionArgType}, + {"GetFunctionArgDefault", (__CPP_FUNC)Cpp::GetFunctionArgDefault}, + {"IsConstMethod", (__CPP_FUNC)Cpp::IsConstMethod}, + {"GetFunctionTemplatedDecls", (__CPP_FUNC)Cpp::GetFunctionTemplatedDecls}, + {"ExistsFunctionTemplate", (__CPP_FUNC)Cpp::ExistsFunctionTemplate}, + {"IsTemplatedFunction", (__CPP_FUNC)Cpp::IsTemplatedFunction}, + {"IsStaticMethod", (__CPP_FUNC)Cpp::IsStaticMethod}, + {"GetClassTemplatedMethods", (__CPP_FUNC)Cpp::GetClassTemplatedMethods}, + {"BestOverloadFunctionMatch", (__CPP_FUNC)Cpp::BestOverloadFunctionMatch}, + {"GetOperatorFromSpelling", (__CPP_FUNC)Cpp::GetOperatorFromSpelling}, + {"IsFunctionDeleted", (__CPP_FUNC)Cpp::IsFunctionDeleted}, + {"IsPublicMethod", (__CPP_FUNC)Cpp::IsPublicMethod}, + {"IsProtectedMethod", (__CPP_FUNC)Cpp::IsProtectedMethod}, + {"IsPrivateMethod", (__CPP_FUNC)Cpp::IsPrivateMethod}, + {"IsConstructor", (__CPP_FUNC)Cpp::IsConstructor}, + {"IsDestructor", (__CPP_FUNC)Cpp::IsDestructor}, + {"GetDatamembers", (__CPP_FUNC)Cpp::GetDatamembers}, + {"GetStaticDatamembers", (__CPP_FUNC)Cpp::GetStaticDatamembers}, + {"GetEnumConstantDatamembers", (__CPP_FUNC)Cpp::GetEnumConstantDatamembers}, + {"LookupDatamember", (__CPP_FUNC)Cpp::LookupDatamember}, + {"IsLambdaClass", (__CPP_FUNC)Cpp::IsLambdaClass}, + {"GetQualifiedName", (__CPP_FUNC)Cpp::GetQualifiedName}, + {"GetVariableOffset", (__CPP_FUNC)Cpp::GetVariableOffset}, + {"IsPublicVariable", (__CPP_FUNC)Cpp::IsPublicVariable}, + {"IsProtectedVariable", (__CPP_FUNC)Cpp::IsProtectedVariable}, + {"IsPrivateVariable", (__CPP_FUNC)Cpp::IsPrivateVariable}, + {"IsStaticVariable", (__CPP_FUNC)Cpp::IsStaticVariable}, + {"IsConstVariable", (__CPP_FUNC)Cpp::IsConstVariable}, + {"GetDimensions", (__CPP_FUNC)Cpp::GetDimensions}, + {"GetEnumConstants", (__CPP_FUNC)Cpp::GetEnumConstants}, + {"GetEnumConstantType", (__CPP_FUNC)Cpp::GetEnumConstantType}, + {"GetEnumConstantValue", (__CPP_FUNC)Cpp::GetEnumConstantValue}, + {"DumpScope", (__CPP_FUNC)Cpp::DumpScope}, + {"AddSearchPath", (__CPP_FUNC)Cpp::AddSearchPath}, + {"Evaluate", (__CPP_FUNC)Cpp::Evaluate}, + {"IsDebugOutputEnabled", (__CPP_FUNC)Cpp::IsDebugOutputEnabled}, + {"EnableDebugOutput", (__CPP_FUNC)Cpp::EnableDebugOutput}, + {nullptr, nullptr} /* end of list */ +}; + +static inline __CPP_FUNC _cppinterop_get_proc_address(const char* funcName) { + static const std::unordered_map function_map = + [] { + std::unordered_map map; + size_t count = 0; + while (api_function_table[count].name != nullptr) + ++count; + map.reserve(count); + + for (size_t i = 0; i < count; ++i) { + map[api_function_table[i].name] = api_function_table[i].address; + } + return map; + }(); + + auto it = function_map.find(funcName); + return (it != function_map.end()) ? it->second : nullptr; +} + +void (*CppGetProcAddress(const unsigned char* procName))(void) { + return _cppinterop_get_proc_address(reinterpret_cast(procName)); +} diff --git a/unittests/CppInterOp/CMakeLists.txt b/unittests/CppInterOp/CMakeLists.txt index 4b4b43bdd..1440c972c 100644 --- a/unittests/CppInterOp/CMakeLists.txt +++ b/unittests/CppInterOp/CMakeLists.txt @@ -11,6 +11,14 @@ else() set(EXTRA_PATH_TEST_BINARIES /CppInterOpTests/unittests/bin/$/) endif() +# Add the DispatchAPITest only when building shared libraries +if (BUILD_SHARED_LIBS) + set_source_files_properties(DispatchAPITest.cpp PROPERTIES COMPILE_DEFINITIONS + "CPPINTEROP_LIB_DIR=\"${CMAKE_BINARY_DIR}/lib/libclangCppInterOp${CMAKE_SHARED_LIBRARY_SUFFIX}\"" + ) + list(APPEND EXTRA_TEST_SOURCE_FILES DispatchAPITest.cpp) +endif() + add_cppinterop_unittest(CppInterOpTests EnumReflectionTest.cpp FunctionReflectionTest.cpp diff --git a/unittests/CppInterOp/DispatchAPITest.cpp b/unittests/CppInterOp/DispatchAPITest.cpp new file mode 100644 index 000000000..303cb45cc --- /dev/null +++ b/unittests/CppInterOp/DispatchAPITest.cpp @@ -0,0 +1,67 @@ +#include "Utils.h" + +#include "CppInterOp/CppInterOpDispatch.h" + +#include "gtest/gtest.h" + +#include + +using namespace TestUtils; +using namespace llvm; +using namespace clang; + +static void* dlGetProcAddress(const char* name) { + static void* handle = dlopen(CPPINTEROP_LIB_DIR, RTLD_LAZY | RTLD_LOCAL); + EXPECT_NE(handle, nullptr) << "Failed to open library: " << dlerror(); + if (!handle) + return nullptr; + static void* gpa = dlsym(handle, "CppGetProcAddress"); + EXPECT_NE(gpa, nullptr) << "Failed to find GetProcAddress: " << dlerror(); + return reinterpret_cast(gpa)(name); +} + +TEST(DispatchAPITestTest, IsClassSymbolLookup) { + CppAPIType::IsClass IsClassFn = + reinterpret_cast(dlGetProcAddress("IsClass")); + ASSERT_NE(IsClassFn, nullptr) << "failed to locate symbol: " << dlerror(); + std::vector Decls; + GetAllTopLevelDecls("namespace N {} class C{}; int I;", Decls); + EXPECT_FALSE(IsClassFn(Decls[0])); + EXPECT_TRUE(IsClassFn(Decls[1])); + EXPECT_FALSE(IsClassFn(Decls[2])); +} + +TEST(DispatchAPITestTest, Demangle) { + + std::string code = R"( + int add(int x, int y) { return x + y; } + int add(double x, double y) { return x + y; } + )"; + + std::vector Decls; + GetAllTopLevelDecls(code, Decls); + EXPECT_EQ(Decls.size(), 2); + + auto Add_int = clang::GlobalDecl(static_cast(Decls[0])); + auto Add_double = clang::GlobalDecl(static_cast(Decls[1])); + + std::string mangled_add_int; + std::string mangled_add_double; + compat::maybeMangleDeclName(Add_int, mangled_add_int); + compat::maybeMangleDeclName(Add_double, mangled_add_double); + + // CppAPIType:: gives us the specific function pointer types + CppAPIType::Demangle DemangleFn = + reinterpret_cast(dlGetProcAddress("Demangle")); + CppAPIType::GetQualifiedCompleteName GetQualifiedCompleteNameFn = + reinterpret_cast( + dlGetProcAddress("GetQualifiedCompleteName")); + + std::string demangled_add_int = DemangleFn(mangled_add_int); + std::string demangled_add_double = DemangleFn(mangled_add_double); + + EXPECT_NE(demangled_add_int.find(GetQualifiedCompleteNameFn(Decls[0])), + std::string::npos); + EXPECT_NE(demangled_add_double.find(GetQualifiedCompleteNameFn(Decls[1])), + std::string::npos); +}