Skip to content

Commit 36ac254

Browse files
committed
Add a class simplifying calls from compiled code to interpreted functions.
1 parent c42c500 commit 36ac254

File tree

3 files changed

+312
-263
lines changed

3 files changed

+312
-263
lines changed

include/clang/Interpreter/CppInterOp.h

Lines changed: 103 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#ifndef CPPINTEROP_CPPINTEROP_H
1111
#define CPPINTEROP_CPPINTEROP_H
1212

13+
#include <cassert>
1314
#include <string>
1415
#include <vector>
1516

@@ -18,11 +19,98 @@ namespace Cpp {
1819
using TCppScope_t = void*;
1920
using TCppType_t = void*;
2021
using TCppFunction_t = void*;
22+
using TCppConstFunction_t = const void*;
2123
using TCppFuncAddr_t = void*;
2224
using TCppSema_t = void *;
2325
using TInterp_t = void*;
2426
using TCppObject_t = void*;
25-
typedef void (*CallFuncWrapper_t)(void *, int, void **, void *);
27+
/// A class modeling function calls for functions produced by the interpreter
28+
/// in compiled code. It provides an information if we are calling a standard
29+
/// function, constructor or destructor.
30+
class JitCall {
31+
public:
32+
friend JitCall MakeFunctionCallable(TInterp_t, TCppConstFunction_t);
33+
enum Kind : char {
34+
kUnknown = 0,
35+
kGenericCall,
36+
kDestructorCall,
37+
};
38+
struct ArgList {
39+
void** m_Args = nullptr;
40+
size_t m_ArgSize = 0;
41+
// Clang struggles with =default...
42+
ArgList() : m_Args(nullptr), m_ArgSize(0) {}
43+
ArgList(void** Args, size_t ArgSize)
44+
: m_Args(Args), m_ArgSize(ArgSize) {}
45+
};
46+
// FIXME: Figure out how to unify the wrapper signatures.
47+
// FIXME: Hide these implementation details by moving wrapper generation in
48+
// this class.
49+
using GenericCall = void (*)(void*, int, void**, void*);
50+
using DestructorCall = void (*)(void*, unsigned long, int);
51+
private:
52+
union {
53+
GenericCall m_GenericCall;
54+
DestructorCall m_DestructorCall;
55+
};
56+
const Kind m_Kind;
57+
TCppConstFunction_t m_FD;
58+
JitCall() : m_Kind(kUnknown), m_GenericCall(nullptr), m_FD(nullptr) {}
59+
JitCall(Kind K, GenericCall C, TCppConstFunction_t FD)
60+
: m_Kind(K), m_GenericCall(C), m_FD(FD) {}
61+
JitCall(Kind K, DestructorCall C, TCppConstFunction_t Dtor)
62+
: m_Kind(K), m_DestructorCall(C), m_FD(Dtor) {}
63+
bool AreArgumentsValid(void* result, ArgList args, void* self) const;
64+
void ReportInvokeStart(void* result, ArgList args, void* self) const;
65+
void ReportInvokeStart(void* object, unsigned long nary,
66+
int withFree) const;
67+
void ReportInvokeEnd() const;
68+
public:
69+
Kind getKind() const { return m_Kind; }
70+
bool isValid() const { return getKind() != kUnknown; }
71+
bool isInvalid() const { return !isValid(); }
72+
explicit operator bool() const { return isValid(); }
73+
74+
// Specialized for calling void functions.
75+
void Invoke(ArgList args = {}, void* self = nullptr) const {
76+
Invoke(/*result=*/nullptr, args, self);
77+
}
78+
79+
/// Makes a call to a generic function or method.
80+
///\param[in] result - the location where the return result will be placed.
81+
///\param[in] args - a pointer to a argument list and argument size.
82+
///\param[in] self - the this pointer of the object.
83+
// FIXME: Adjust the arguments and their types: args_size can be unsigned;
84+
// self can go in the end and be nullptr by default; result can be a nullptr
85+
// by default. These changes should be syncronized with the wrapper if we
86+
// decide to directly.
87+
void Invoke(void* result, ArgList args = {}, void* self = nullptr) const {
88+
// Forward if we intended to call a dtor with only 1 parameter.
89+
if (m_Kind == kDestructorCall && result && !args.m_Args)
90+
return InvokeDestructor(result, /*nary=*/0UL, /*withFree=*/true);
91+
92+
#ifndef NDEBUG
93+
assert(AreArgumentsValid(result, args, self) && "Invalid args!");
94+
ReportInvokeStart(result, args, self);
95+
#endif // NDEBUG
96+
m_GenericCall(self, args.m_ArgSize, args.m_Args, result);
97+
}
98+
/// Makes a call to a destructor.
99+
///\param[in] object - the pointer of the object whose destructor we call.
100+
///\param[in] nary - the count of the objects we destruct if we deal with an
101+
/// array of objects.
102+
///\param[in] withFree - true if we should call operator delete or false if
103+
/// we should call only the destructor.
104+
//FIXME: Change the type of withFree from int to bool in the wrapper code.
105+
void InvokeDestructor(void* object, unsigned long nary = 0,
106+
int withFree = true) const {
107+
assert(m_Kind == kDestructorCall && "Wrong overload!");
108+
#ifndef NDEBUG
109+
ReportInvokeStart(object, nary, withFree);
110+
#endif // NDEBUG
111+
m_DestructorCall(object, nary, withFree);
112+
}
113+
};
26114

27115
/// Enables or disables the debugging printouts on stderr.
28116
void EnableDebugOutput(bool value = true);
@@ -109,9 +197,14 @@ namespace Cpp {
109197
std::vector<TCppFunction_t> GetClassMethods(TCppSema_t sema,
110198
TCppScope_t klass);
111199

200+
///\returns if a class has a default constructor.
112201
bool HasDefaultConstructor(TCppScope_t scope);
113202

114-
TCppScope_t GetDestructor(TCppScope_t scope);
203+
///\returns the default constructor of a class if any.
204+
TCppFunction_t GetDefaultConstructor(TCppSema_t sema, TCppScope_t scope);
205+
206+
///\returns the class destructor.
207+
TCppFunction_t GetDestructor(TCppScope_t scope);
115208

116209
std::vector<TCppFunction_t> GetFunctionsUsingName(TCppSema_t sema,
117210
TCppScope_t scope,
@@ -121,7 +214,7 @@ namespace Cpp {
121214

122215
TCppIndex_t GetFunctionNumArgs(TCppFunction_t func);
123216

124-
TCppIndex_t GetFunctionRequiredArgs(TCppFunction_t func);
217+
TCppIndex_t GetFunctionRequiredArgs(TCppConstFunction_t func);
125218

126219
TCppType_t GetFunctionArgType(TCppFunction_t func, TCppIndex_t iarg);
127220

@@ -134,15 +227,17 @@ namespace Cpp {
134227
bool ExistsFunctionTemplate(TCppSema_t sema, const std::string &name,
135228
TCppScope_t parent = 0);
136229

230+
bool IsMethod(TCppConstFunction_t method);
231+
137232
bool IsPublicMethod(TCppFunction_t method);
138233

139234
bool IsProtectedMethod(TCppFunction_t method);
140235

141236
bool IsPrivateMethod(TCppFunction_t method);
142237

143-
bool IsConstructor(TCppFunction_t method);
238+
bool IsConstructor(TCppConstFunction_t method);
144239

145-
bool IsDestructor(TCppFunction_t method);
240+
bool IsDestructor(TCppConstFunction_t method);
146241

147242
bool IsStaticMethod(TCppFunction_t method);
148243

@@ -188,8 +283,9 @@ namespace Cpp {
188283
/// Check if a C++ type derives from another.
189284
bool IsTypeDerivedFrom(TInterp_t interp, TCppType_t derived, TCppType_t base);
190285

191-
CallFuncWrapper_t GetFunctionCallWrapper(TInterp_t interp,
192-
TCppFunction_t func);
286+
/// Creates a trampoline function by using the interpreter and returns a
287+
/// uniform interface to call it from compiled code.
288+
JitCall MakeFunctionCallable(TInterp_t interp, TCppConstFunction_t func);
193289

194290
/// Checks if a function declared is of const type or not
195291
bool IsConstMethod(TCppFunction_t method);

0 commit comments

Comments
 (0)