Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TClingCallFunc.h
Go to the documentation of this file.
1 // root/core/meta
2 // vim: sw=3
3 // Author: Paul Russo 30/07/2012
4 
5 /*************************************************************************
6  * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers. *
7  * All rights reserved. *
8  * *
9  * For the licensing terms see $ROOTSYS/LICENSE. *
10  * For the list of contributors see $ROOTSYS/README/CREDITS. *
11  *************************************************************************/
12 
13 #ifndef ROOT_CallFunc
14 #define ROOT_CallFunc
15 
16 //////////////////////////////////////////////////////////////////////////
17 // //
18 // TClingCallFunc //
19 // //
20 // Emulation of the CINT CallFunc class. //
21 // //
22 // The CINT C++ interpreter provides an interface for calling //
23 // functions through the generated wrappers in dictionaries with //
24 // the CallFunc class. This class provides the same functionality, //
25 // using an interface as close as possible to CallFunc but the //
26 // function metadata and calling service comes from the Cling //
27 // C++ interpreter and the Clang C++ compiler, not CINT. //
28 // //
29 //////////////////////////////////////////////////////////////////////////
30 
31 #include "TClingMethodInfo.h"
32 #include "TClingClassInfo.h"
33 #include "TInterpreter.h"
34 
35 #include "cling/Interpreter/Value.h"
36 
37 #include <llvm/ADT/SmallVector.h>
38 
39 namespace clang {
40 class BuiltinType;
41 class Expr;
42 class FunctionDecl;
43 class CXXMethodDecl;
44 }
45 
46 namespace cling {
47 class Interpreter;
48 }
49 
50 class TClingClassInfo;
51 class TInterpreterValue;
52 
53 typedef void (*tcling_callfunc_Wrapper_t)(void*, int, void**, void*);
54 typedef void (*tcling_callfunc_ctor_Wrapper_t)(void**, void*, unsigned long);
55 typedef void (*tcling_callfunc_dtor_Wrapper_t)(void*, unsigned long, int);
56 
57 class TClingCallFunc {
58 
59 private:
60 
61  /// Cling interpreter, we do *not* own.
62  cling::Interpreter* fInterp;
63  /// ROOT normalized context for that interpreter
64  const ROOT::TMetaUtils::TNormalizedCtxt &fNormCtxt;
65  /// Current method, we own.
66  std::unique_ptr<TClingMethodInfo> fMethod;
67  /// Decl for the method
68  const clang::FunctionDecl *fDecl = nullptr;
69  /// Number of required arguments
70  size_t fMinRequiredArguments = -1;
71  /// Pointer to compiled wrapper, we do *not* own.
72  tcling_callfunc_Wrapper_t fWrapper;
73  /// Stored function arguments, we own.
74  mutable llvm::SmallVector<cling::Value, 8> fArgVals;
75  /// If true, do not limit number of function arguments to declared number.
76  bool fIgnoreExtraArgs : 1;
77  bool fReturnIsRecordType : 1;
78 
79 private:
80  enum EReferenceType {
81  kNotReference,
82  kLValueReference,
83  kRValueReference
84  };
85 
86  using ExecWithRetFunc_t = std::function<void(void* address, cling::Value &ret)>;
87 
88  void* compile_wrapper(const std::string& wrapper_name,
89  const std::string& wrapper,
90  bool withAccessControl = true);
91 
92  void collect_type_info(clang::QualType& QT, std::ostringstream& typedefbuf,
93  std::ostringstream& callbuf, std::string& type_name,
94  EReferenceType& refType, bool& isPointer, int indent_level,
95  bool forArgument);
96 
97  void make_narg_call(const std::string &return_type, const unsigned N, std::ostringstream &typedefbuf,
98  std::ostringstream &callbuf, const std::string &class_name, int indent_level);
99 
100  void make_narg_ctor(const unsigned N, std::ostringstream& typedefbuf,
101  std::ostringstream& callbuf,
102  const std::string& class_name, int indent_level);
103 
104  void make_narg_call_with_return(const unsigned N,
105  const std::string& class_name,
106  std::ostringstream& buf, int indent_level);
107 
108  void make_narg_ctor_with_return(const unsigned N,
109  const std::string& class_name,
110  std::ostringstream& buf, int indent_level);
111 
112  tcling_callfunc_Wrapper_t make_wrapper();
113 
114  tcling_callfunc_ctor_Wrapper_t
115  make_ctor_wrapper(const TClingClassInfo* info);
116 
117  tcling_callfunc_dtor_Wrapper_t
118  make_dtor_wrapper(const TClingClassInfo* info);
119 
120  // Implemented in source file.
121  template <typename T>
122  void execWithLL(void* address, cling::Value* val);
123  template <typename T>
124  void execWithULL(void* address, cling::Value* val);
125  template <class T>
126  ExecWithRetFunc_t InitRetAndExecIntegral(clang::QualType QT, cling::Value &ret);
127 
128  ExecWithRetFunc_t InitRetAndExecBuiltin(clang::QualType QT, const clang::BuiltinType *BT, cling::Value &ret);
129  ExecWithRetFunc_t InitRetAndExecNoCtor(clang::QualType QT, cling::Value &ret);
130  ExecWithRetFunc_t InitRetAndExec(const clang::FunctionDecl *FD, cling::Value &ret);
131 
132  void exec(void* address, void* ret);
133 
134  void exec_with_valref_return(void* address,
135  cling::Value* ret);
136  void EvaluateArgList(const std::string& ArgList);
137 
138  size_t CalculateMinRequiredArguments();
139 
140  size_t GetMinRequiredArguments() {
141  if (fMinRequiredArguments == (size_t)-1)
142  fMinRequiredArguments = CalculateMinRequiredArguments();
143  return fMinRequiredArguments;
144  }
145 
146  // Implemented in source file.
147  template <typename T>
148  T ExecT(void* address);
149 
150 
151 public:
152 
153  ~TClingCallFunc() = default;
154 
155  explicit TClingCallFunc(cling::Interpreter *interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
156  : fInterp(interp), fNormCtxt(normCtxt), fWrapper(0), fIgnoreExtraArgs(false), fReturnIsRecordType(false)
157  {
158  fMethod = std::unique_ptr<TClingMethodInfo>(new TClingMethodInfo(interp));
159  }
160 
161  explicit TClingCallFunc(const TClingMethodInfo &minfo, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
162  : fInterp(minfo.GetInterpreter()), fNormCtxt(normCtxt), fWrapper(0), fIgnoreExtraArgs(false),
163  fReturnIsRecordType(false)
164 
165  {
166  fMethod = std::unique_ptr<TClingMethodInfo>(new TClingMethodInfo(minfo));
167  }
168 
169  TClingCallFunc(const TClingCallFunc &rhs)
170  : fInterp(rhs.fInterp), fNormCtxt(rhs.fNormCtxt), fWrapper(rhs.fWrapper), fArgVals(rhs.fArgVals),
171  fIgnoreExtraArgs(rhs.fIgnoreExtraArgs), fReturnIsRecordType(rhs.fReturnIsRecordType)
172  {
173  fMethod = std::unique_ptr<TClingMethodInfo>(new TClingMethodInfo(*rhs.fMethod));
174  }
175 
176  TClingCallFunc &operator=(const TClingCallFunc &rhs) = delete;
177 
178  void* ExecDefaultConstructor(const TClingClassInfo* info, void* address = 0,
179  unsigned long nary = 0UL);
180  void ExecDestructor(const TClingClassInfo* info, void* address = 0,
181  unsigned long nary = 0UL, bool withFree = true);
182  void ExecWithReturn(void* address, void* ret = 0);
183  void ExecWithArgsAndReturn(void* address,
184  const void* args[] = 0,
185  int nargs = 0,
186  void* ret = 0);
187  void Exec(void* address, TInterpreterValue* interpVal = 0);
188  long ExecInt(void* address);
189  long long ExecInt64(void* address);
190  double ExecDouble(void* address);
191  TClingMethodInfo* FactoryMethod() const;
192  void IgnoreExtraArgs(bool ignore) { fIgnoreExtraArgs = ignore; }
193  void Init();
194  void Init(const TClingMethodInfo&);
195  void Init(std::unique_ptr<TClingMethodInfo>);
196  void Invoke(cling::Value* result = 0) const;
197  void* InterfaceMethod();
198  bool IsValid() const;
199  TInterpreter::CallFuncIFacePtr_t IFacePtr();
200  const clang::FunctionDecl *GetDecl() {
201  if (!fDecl)
202  fDecl = fMethod->GetMethodDecl();
203  return fDecl;
204  }
205 
206  int get_wrapper_code(std::string &wrapper_name, std::string &wrapper);
207 
208  const clang::FunctionDecl* GetDecl() const {
209  if (fDecl)
210  return fDecl;
211  return fMethod->GetMethodDecl();
212  }
213  void ResetArg();
214  void SetArg(long arg);
215  void SetArg(unsigned long arg);
216  void SetArg(float arg);
217  void SetArg(double arg);
218  void SetArg(long long arg);
219  void SetArg(unsigned long long arg);
220  void SetArgArray(long* argArr, int narg);
221  void SetArgs(const char* args);
222  void SetFunc(const TClingClassInfo* info, const char* method,
223  const char* arglist, long* poffset);
224  void SetFunc(const TClingClassInfo* info, const char* method,
225  const char* arglist, bool objectIsConst, long* poffset);
226  void SetFunc(const TClingMethodInfo* info);
227  void SetFuncProto(const TClingClassInfo* info, const char* method,
228  const char* proto, long* poffset,
229  ROOT::EFunctionMatchMode mode = ROOT::kConversionMatch);
230  void SetFuncProto(const TClingClassInfo* info, const char* method,
231  const char* proto, bool objectIsConst, long* poffset,
232  ROOT::EFunctionMatchMode mode = ROOT::kConversionMatch);
233  void SetFuncProto(const TClingClassInfo* info, const char* method,
234  const llvm::SmallVectorImpl<clang::QualType>& proto,
235  long* poffset,
236  ROOT::EFunctionMatchMode mode = ROOT::kConversionMatch);
237  void SetFuncProto(const TClingClassInfo* info, const char* method,
238  const llvm::SmallVectorImpl<clang::QualType>& proto,
239  bool objectIsConst, long* poffset,
240  ROOT::EFunctionMatchMode mode = ROOT::kConversionMatch);
241 };
242 
243 #endif // ROOT_CallFunc