Reduce the amount of headers needed by the dynamic scopes at runtime:
* Make GenericValue, clang::QualType opaque in Value * Move LifetimeHandler implementation into source; requires separate header * Also: * Value: replace CPP macros by overloads git-svn-id: http://root.cern.ch/svn/root/trunk@48675 27541ba8-7e3a-0410-8455-c3a389f83636
This commit is contained in:
parent
e0397a6d4c
commit
664e8b22ac
85
include/cling/Interpreter/DynamicLookupLifetimeHandler.h
Normal file
85
include/cling/Interpreter/DynamicLookupLifetimeHandler.h
Normal file
@ -0,0 +1,85 @@
|
||||
//--------------------------------------------------------------------*- C++ -*-
|
||||
// CLING - the C++ LLVM-based InterpreterG :)
|
||||
// version: $Id$
|
||||
// author: Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
|
||||
//------------------------------------------------------------------------------
|
||||
#ifndef CLING_DYNAMIC_LOOKUP_LIFETIME_HANDLER_H
|
||||
#define CLING_DYNAMIC_LOOKUP_LIFETIME_HANDLER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace clang {
|
||||
class DeclContext;
|
||||
}
|
||||
|
||||
namespace cling {
|
||||
class DynamicExprInfo;
|
||||
class Interpreter;
|
||||
|
||||
/// \brief Contains declarations for cling's runtime.
|
||||
namespace runtime {
|
||||
|
||||
/// \brief Provides private definitions for the dynamic scopes and runtime
|
||||
/// bindings. These builtins should not be used for other purposes.
|
||||
namespace internal {
|
||||
extern Interpreter* gCling;
|
||||
|
||||
/// \brief LifetimeHandler is used in case of initialization using address
|
||||
/// on the automatic store (stack) instead of EvaluateT.
|
||||
///
|
||||
/// The reason is to avoid the copy constructors that might be private.
|
||||
/// This is part of complex transformation, which aims to preserve the
|
||||
/// code behavior. For example:
|
||||
/// @code
|
||||
/// int i = 5;
|
||||
/// MyClass my(dep->Symbol(i))
|
||||
/// @endcode
|
||||
/// where dep->Symbol() is a symbol not known at compile-time
|
||||
/// transformed into:
|
||||
/// @code
|
||||
/// cling::runtime::internal::LifetimeHandler
|
||||
/// __unique("dep->Sybmol(*(int*)@)",(void*[]){&i}, DC, "MyClass");
|
||||
/// MyClass &my(*(MyClass*)__unique.getMemory());
|
||||
/// @endcode
|
||||
class LifetimeHandler {
|
||||
private:
|
||||
/// \brief The Interpreter handling this storage element.
|
||||
Interpreter* m_Interpreter;
|
||||
|
||||
/// \brief The memory on the free store, where the object will be
|
||||
/// created.
|
||||
void* m_Memory;
|
||||
|
||||
/// \brief The type of the object that will be created.
|
||||
std::string m_Type;
|
||||
|
||||
public:
|
||||
/// \brief Constructs an expression, which creates the object on the
|
||||
/// free store and tells the interpreter to evaluate it.
|
||||
///
|
||||
/// @param[in] ExprInfo Helper structure that keeps information about
|
||||
/// the expression that is being replaced and the addresses of the
|
||||
/// variables that the replaced expression contains.
|
||||
/// @param[in] DC The declaration context, in which the expression will
|
||||
/// be evaluated at runtime
|
||||
/// @param[in] type The type of the object, which will help to delete
|
||||
/// it, when the LifetimeHandler goes out of scope.
|
||||
///
|
||||
LifetimeHandler(DynamicExprInfo* ExprInfo,
|
||||
clang::DeclContext* DC,
|
||||
const char* type,
|
||||
Interpreter* Interp = gCling);
|
||||
|
||||
///\brief Returns the created object.
|
||||
void* getMemory() const { return m_Memory; }
|
||||
|
||||
/// \brief Clears up the free store, when LifetimeHandler goes out of
|
||||
/// scope.
|
||||
///
|
||||
~LifetimeHandler();
|
||||
};
|
||||
}
|
||||
} // end namespace runtime
|
||||
} // end namespace cling
|
||||
|
||||
#endif // CLING_DYNAMIC_LOOKUP_LIFETIME_HANDLER_H
|
@ -17,17 +17,12 @@
|
||||
#include "cling/Interpreter/RuntimeUniverse.h"
|
||||
#endif
|
||||
#include "cling/Interpreter/DynamicExprInfo.h"
|
||||
#include "cling/Interpreter/ValuePrinter.h"
|
||||
#include "cling/Interpreter/DynamicLookupLifetimeHandler.h"
|
||||
#include "cling/Interpreter/StoredValueRef.h"
|
||||
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace cling {
|
||||
|
||||
/// \brief Used to stores the declarations, which are going to be
|
||||
/// available only at runtime. These are cling runtime builtins.
|
||||
/// \brief Contains declarations for cling's runtime.
|
||||
namespace runtime {
|
||||
|
||||
/// \brief Provides builtins, which are neccessary for the dynamic scopes
|
||||
@ -68,71 +63,6 @@ namespace runtime {
|
||||
cling::runtime::gCling->Evaluate(ExprInfo->getExpr(), DC,
|
||||
ExprInfo->isValuePrinterRequested());
|
||||
}
|
||||
|
||||
/// \brief LifetimeHandler is used in case of initialization using address
|
||||
/// on the automatic store (stack) instead of EvaluateT.
|
||||
///
|
||||
/// The reason is to avoid the copy constructors that might be private.
|
||||
/// This is part of complex transformation, which aims to preserve the
|
||||
/// code behavior. For example:
|
||||
/// @code
|
||||
/// int i = 5;
|
||||
/// MyClass my(dep->Symbol(i))
|
||||
/// @endcode
|
||||
/// where dep->Symbol() is a symbol not known at compile-time
|
||||
/// transformed into:
|
||||
/// @code
|
||||
/// cling::runtime::internal::LifetimeHandler
|
||||
/// __unique("dep->Sybmol(*(int*)@)",(void*[]){&i}, DC, "MyClass");
|
||||
/// MyClass &my(*(MyClass*)__unique.getMemory());
|
||||
/// @endcode
|
||||
class LifetimeHandler {
|
||||
private:
|
||||
/// \brief The memory on the free store, where the object will be
|
||||
/// created.
|
||||
void* m_Memory;
|
||||
|
||||
/// \brief The type of the object that will be created.
|
||||
std::string m_Type;
|
||||
public:
|
||||
/// \brief Constructs an expression, which creates the object on the
|
||||
/// free store and tells the interpreter to evaluate it.
|
||||
///
|
||||
/// @param[in] ExprInfo Helper structure that keeps information about
|
||||
/// the expression that is being replaced and the addresses of the
|
||||
/// variables that the replaced expression contains.
|
||||
/// @param[in] DC The declaration context, in which the expression will
|
||||
/// be evaluated at runtime
|
||||
/// @param[in] type The type of the object, which will help to delete
|
||||
/// it, when the LifetimeHandler goes out of scope.
|
||||
///
|
||||
LifetimeHandler(DynamicExprInfo* ExprInfo,
|
||||
clang::DeclContext* DC,
|
||||
const char* type) {
|
||||
m_Type = type;
|
||||
std::string ctor("new ");
|
||||
ctor += type;
|
||||
ctor += ExprInfo->getExpr();
|
||||
StoredValueRef res = cling::runtime::gCling->Evaluate(ctor.c_str(), DC,
|
||||
ExprInfo->isValuePrinterRequested()
|
||||
);
|
||||
m_Memory = (void*)res.get().getGV().PointerVal;
|
||||
}
|
||||
|
||||
///\brief Returns the created object.
|
||||
void* getMemory() const { return m_Memory; }
|
||||
|
||||
/// \brief Clears up the free store, when LifetimeHandler goes out of
|
||||
/// scope.
|
||||
///
|
||||
~LifetimeHandler() {
|
||||
std::string str;
|
||||
llvm::raw_string_ostream stream(str);
|
||||
stream<<"delete ("<< m_Type << "*) "<< m_Memory << ";";
|
||||
stream.flush();
|
||||
cling::runtime::gCling->execute(str);
|
||||
}
|
||||
};
|
||||
}
|
||||
} // end nmespace internal
|
||||
} // end namespace runtime
|
||||
} // end namespace cling
|
||||
|
@ -3,16 +3,13 @@
|
||||
// version: $Id$
|
||||
// author: Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
|
||||
//------------------------------------------------------------------------------
|
||||
#ifndef __CLING__
|
||||
#error "This file must not be included by compiled programs."
|
||||
#else
|
||||
|
||||
#ifdef CLING_RUNTIME_UNIVERSE_H
|
||||
#error "CLING_RUNTIME_UNIVERSE_H Must only include once."
|
||||
#else
|
||||
|
||||
#ifndef CLING_RUNTIME_UNIVERSE_H
|
||||
#define CLING_RUNTIME_UNIVERSE_H
|
||||
|
||||
#if !defined(__CLING__) && !defined(__COMPILING_CLING__)
|
||||
#error "This file must not be included by compiled programs."
|
||||
#endif
|
||||
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS // needed by System/DataTypes.h
|
||||
#endif
|
||||
@ -90,6 +87,4 @@ extern "C" {
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // CLING_RUNTIME_UNIVERSE_H (error)
|
||||
|
||||
#endif // __CLING__
|
||||
#endif // CLING_RUNTIME_UNIVERSE_H
|
||||
|
@ -26,7 +26,7 @@ namespace cling {
|
||||
|
||||
/// \brief Number of bytes that need to be allocated to hold a value
|
||||
/// of our type
|
||||
int64_t getAllocSizeInBytes(const clang::ASTContext& ctx) const;
|
||||
long long getAllocSizeInBytes(const clang::ASTContext& ctx) const;
|
||||
|
||||
/// \brief Memory allocated for value, owned by this value
|
||||
///
|
||||
|
@ -7,14 +7,16 @@
|
||||
#ifndef CLING_VALUE_H
|
||||
#define CLING_VALUE_H
|
||||
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/CanonicalType.h"
|
||||
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
#include "llvm/Type.h"
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
namespace llvm {
|
||||
class Type;
|
||||
struct GenericValue;
|
||||
}
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class QualType;
|
||||
}
|
||||
|
||||
namespace cling {
|
||||
@ -32,35 +34,43 @@ namespace cling {
|
||||
/// void types
|
||||
/// 3. Parameters for calls given an llvm::Function and a clang::FunctionDecl.
|
||||
class Value {
|
||||
private:
|
||||
/// \brief Forward decl for typed access specializations
|
||||
template <typename T> struct TypedAccess;
|
||||
|
||||
protected:
|
||||
/// \brief value
|
||||
llvm::GenericValue m_GV;
|
||||
char /*llvm::GenericValue*/ m_GV[32]; // 24 bytes on 64bit
|
||||
|
||||
/// \brief the value's type according to clang
|
||||
clang::QualType m_ClangType;
|
||||
/// \brief the value's type according to clang, stored as void* to reduce
|
||||
/// dependencies.
|
||||
void* /*clang::QualType*/ m_ClangType;
|
||||
|
||||
/// \brief the value's type according to clang
|
||||
const llvm::Type* m_LLVMType;
|
||||
|
||||
enum EStorageType {
|
||||
kSignedIntegerOrEnumerationType,
|
||||
kUnsignedIntegerOrEnumerationType,
|
||||
kDoubleType,
|
||||
kFloatType,
|
||||
kLongDoubleType,
|
||||
kPointerType,
|
||||
kUnsupportedType
|
||||
};
|
||||
|
||||
/// \brief Retrieve the underlying, canonical, desugared, unqualified type.
|
||||
EStorageType getStorageType() const;
|
||||
|
||||
public:
|
||||
|
||||
/// \brief Default constructor, creates a value that IsInvalid().
|
||||
Value() {}
|
||||
/// \brief Construct a valid Value.
|
||||
Value(const llvm::GenericValue& v, clang::QualType t)
|
||||
: m_GV(v), m_ClangType(t), m_LLVMType(0) { }
|
||||
Value(const llvm::GenericValue& v, clang::QualType t);
|
||||
|
||||
Value(const llvm::GenericValue& v, clang::QualType clangTy,
|
||||
const llvm::Type* llvmTy)
|
||||
: m_GV(v), m_ClangType(clangTy), m_LLVMType(llvmTy) { }
|
||||
const llvm::Type* llvmTy);
|
||||
|
||||
llvm::GenericValue getGV() const { return m_GV; }
|
||||
void setGV(llvm::GenericValue GV) { m_GV = GV; }
|
||||
clang::QualType getClangType() const { return m_ClangType; }
|
||||
llvm::GenericValue getGV() const;
|
||||
void setGV(llvm::GenericValue GV);
|
||||
clang::QualType getClangType() const;
|
||||
const llvm::Type* getLLVMType() const { return m_LLVMType; }
|
||||
void setLLVMType(const llvm::Type* Ty) { m_LLVMType = Ty; }
|
||||
|
||||
@ -68,13 +78,10 @@ namespace cling {
|
||||
//
|
||||
/// Determine whether the Value has been set by checking
|
||||
/// whether the type is valid.
|
||||
bool isValid() const { return !m_ClangType.isNull(); }
|
||||
bool isValid() const;
|
||||
|
||||
/// \brief Determine whether the Value is set but void.
|
||||
bool isVoid(const clang::ASTContext& ASTContext) const {
|
||||
return isValid()
|
||||
&& m_ClangType.getDesugaredType(ASTContext)->isVoidType();
|
||||
}
|
||||
bool isVoid(const clang::ASTContext& ASTContext) const;
|
||||
|
||||
/// \brief Determine whether the Value is set and not void.
|
||||
//
|
||||
@ -87,6 +94,24 @@ namespace cling {
|
||||
template <typename T>
|
||||
T getAs() const;
|
||||
|
||||
template <typename T>
|
||||
T* getAs(T**) const { return (T*)getAs((void**)0); }
|
||||
void* getAs(void**) const;
|
||||
double getAs(double*) const;
|
||||
long double getAs(long double*) const;
|
||||
float getAs(float*) const;
|
||||
bool getAs(bool*) const;
|
||||
signed char getAs(signed char*) const;
|
||||
unsigned char getAs(unsigned char*) const;
|
||||
signed short getAs(signed short*) const;
|
||||
unsigned short getAs(unsigned short*) const;
|
||||
signed int getAs(signed int*) const;
|
||||
unsigned int getAs(unsigned int*) const;
|
||||
signed long getAs(signed long*) const;
|
||||
unsigned long getAs(unsigned long*) const;
|
||||
signed long long getAs(signed long long*) const;
|
||||
unsigned long long getAs(unsigned long long*) const;
|
||||
|
||||
/// \brief Get the value.
|
||||
//
|
||||
/// Get the value cast to T. This is similar to reinterpret_cast<T>(value),
|
||||
@ -96,83 +121,31 @@ namespace cling {
|
||||
T simplisticCastAs() const;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Value::TypedAccess{
|
||||
T extract(const llvm::GenericValue& value) {
|
||||
return *reinterpret_cast<T*>(value.PointerVal);
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct Value::TypedAccess<T*>{
|
||||
T* extract(const llvm::GenericValue& value) {
|
||||
return reinterpret_cast<T*>(value.PointerVal);
|
||||
}
|
||||
};
|
||||
|
||||
#define CLING_VALUE_TYPEDACCESS(TYPE, GETTER) \
|
||||
template<> \
|
||||
struct Value::TypedAccess<TYPE> { \
|
||||
TYPE extract(const llvm::GenericValue& value) { \
|
||||
return value.GETTER; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CLING_VALUE_TYPEDACCESS_SIGNED(TYPE) \
|
||||
CLING_VALUE_TYPEDACCESS(signed TYPE, IntVal.getSExtValue())
|
||||
|
||||
#define CLING_VALUE_TYPEDACCESS_UNSIGNED(TYPE) \
|
||||
CLING_VALUE_TYPEDACCESS(unsigned TYPE, IntVal.getZExtValue())
|
||||
|
||||
#define CLING_VALUE_TYPEDACCESS_BOTHSIGNS(TYPE) \
|
||||
CLING_VALUE_TYPEDACCESS_SIGNED(TYPE); \
|
||||
CLING_VALUE_TYPEDACCESS_UNSIGNED(TYPE);
|
||||
|
||||
CLING_VALUE_TYPEDACCESS(double, DoubleVal);
|
||||
//CLING_VALUE_TYPEDACCESS(long double, ???);
|
||||
CLING_VALUE_TYPEDACCESS(float, FloatVal);
|
||||
|
||||
CLING_VALUE_TYPEDACCESS(bool, IntVal.getBoolValue());
|
||||
|
||||
CLING_VALUE_TYPEDACCESS_BOTHSIGNS(char)
|
||||
CLING_VALUE_TYPEDACCESS_BOTHSIGNS(short)
|
||||
CLING_VALUE_TYPEDACCESS_BOTHSIGNS(int)
|
||||
CLING_VALUE_TYPEDACCESS_BOTHSIGNS(long)
|
||||
CLING_VALUE_TYPEDACCESS_BOTHSIGNS(long long)
|
||||
|
||||
#undef CLING_VALUE_TYPEDACCESS_BOTHSIGNS
|
||||
#undef CLING_VALUE_TYPEDACCESS_UNSIGNED
|
||||
#undef CLING_VALUE_TYPEDACCESS_SIGNED
|
||||
#undef CLING_VALUE_TYPEDACCESS
|
||||
|
||||
template <typename T>
|
||||
T Value::getAs() const {
|
||||
// T *must* correspond to type. Else use simplisticCastAs()!
|
||||
TypedAccess<T> VI;
|
||||
return VI.extract(m_GV);
|
||||
return getAs((T*)0);
|
||||
}
|
||||
template <typename T>
|
||||
T Value::simplisticCastAs() const {
|
||||
const clang::Type* desugCanon = m_ClangType->getUnqualifiedDesugaredType();
|
||||
desugCanon = desugCanon->getCanonicalTypeUnqualified()->getTypePtr()
|
||||
->getUnqualifiedDesugaredType();
|
||||
if (desugCanon->isSignedIntegerOrEnumerationType()) {
|
||||
EStorageType storageType = getStorageType();
|
||||
switch (storageType) {
|
||||
case kSignedIntegerOrEnumerationType:
|
||||
return (T) getAs<signed long long>();
|
||||
} else if (desugCanon->isUnsignedIntegerOrEnumerationType()) {
|
||||
case kUnsignedIntegerOrEnumerationType:
|
||||
return (T) getAs<unsigned long long>();
|
||||
} else if (desugCanon->isRealFloatingType()) {
|
||||
const clang::BuiltinType* BT = desugCanon->getAs<clang::BuiltinType>();
|
||||
if (BT->getKind() == clang::BuiltinType::Double)
|
||||
return (T) getAs<double>();
|
||||
else if (BT->getKind() == clang::BuiltinType::Float)
|
||||
return (T) getAs<float>();
|
||||
/* not yet supported in JIT:
|
||||
else if (BT->getKind() == clang::BuiltinType::LongDouble)
|
||||
return (T) getAs<long double>();
|
||||
*/
|
||||
} else if (desugCanon->isPointerType() || desugCanon->isObjectType()) {
|
||||
case kDoubleType:
|
||||
return (T) getAs<double>();
|
||||
case kFloatType:
|
||||
return (T) getAs<float>();
|
||||
case kLongDoubleType:
|
||||
return (T) getAs<long double>();
|
||||
case kPointerType:
|
||||
return (T) (size_t) getAs<void*>();
|
||||
case kUnsupportedType:
|
||||
assert("unsupported type in Value, cannot cast simplistically!" && 0);
|
||||
}
|
||||
assert("unsupported type in Value, cannot cast simplistically!" && 0);
|
||||
return T();
|
||||
}
|
||||
} // end namespace cling
|
||||
|
@ -8,9 +8,13 @@
|
||||
|
||||
#include "cling/Interpreter/Interpreter.h"
|
||||
#include "cling/Interpreter/InterpreterCallbacks.h"
|
||||
#include "cling/Interpreter/DynamicExprInfo.h"
|
||||
#include "cling/Interpreter/StoredValueRef.h"
|
||||
#include "cling/Interpreter/Transaction.h"
|
||||
#include "cling/Utils/AST.h"
|
||||
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
@ -18,6 +22,8 @@
|
||||
#include "clang/Sema/Lookup.h"
|
||||
#include "clang/Sema/Template.h"
|
||||
|
||||
#include "cling/Interpreter/DynamicLookupLifetimeHandler.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
namespace {
|
||||
@ -362,7 +368,8 @@ namespace cling {
|
||||
llvm::SmallVector<Expr*, 4> Inits;
|
||||
// Add MyClass in LifetimeHandler unique(DynamicExprInfo* ExprInfo
|
||||
// DC,
|
||||
// "MyClass")
|
||||
// "MyClass"
|
||||
// /*, Interp = gCling*/)
|
||||
// Build Arg0 DynamicExprInfo
|
||||
Inits.push_back(BuildDynamicExprInfo(E));
|
||||
// Build Arg1 DeclContext* DC
|
||||
@ -651,7 +658,7 @@ namespace cling {
|
||||
}
|
||||
|
||||
Expr* EvaluateTSynthesizer::ConstructCStyleCasePtrExpr(QualType Ty,
|
||||
uint64_t Ptr) {
|
||||
uint64_t Ptr) {
|
||||
if (!Ty->isPointerType())
|
||||
Ty = m_Context->getPointerType(Ty);
|
||||
TypeSourceInfo* TSI = m_Context->CreateTypeSourceInfo(Ty);
|
||||
@ -825,4 +832,30 @@ namespace cling {
|
||||
|
||||
// end Helpers
|
||||
|
||||
namespace runtime {
|
||||
namespace internal {
|
||||
// Implementations from DynamicLookupLifetimeHandler.h
|
||||
LifetimeHandler::LifetimeHandler(DynamicExprInfo* ExprInfo,
|
||||
clang::DeclContext* DC,
|
||||
const char* type,
|
||||
Interpreter* Interp /* = gCling */):
|
||||
m_Interpreter(Interp), m_Type(type) {
|
||||
std::string ctor("new ");
|
||||
ctor += type;
|
||||
ctor += ExprInfo->getExpr();
|
||||
StoredValueRef res = Interp->Evaluate(ctor.c_str(), DC,
|
||||
ExprInfo->isValuePrinterRequested()
|
||||
);
|
||||
m_Memory = (void*)res.get().getGV().PointerVal;
|
||||
}
|
||||
|
||||
LifetimeHandler::~LifetimeHandler() {
|
||||
std::string str;
|
||||
llvm::raw_string_ostream stream(str);
|
||||
stream << "delete (" << m_Type << "*) " << m_Memory << ";";
|
||||
stream.flush();
|
||||
m_Interpreter->execute(str);
|
||||
}
|
||||
} // end namespace internal
|
||||
} // end namespace runtime
|
||||
} // end namespace cling
|
||||
|
@ -8,12 +8,15 @@
|
||||
|
||||
#include "cling/Interpreter/StoredValueRef.h"
|
||||
|
||||
#include "clang/AST/Type.h"
|
||||
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/PassManager.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Analysis/Verifier.h"
|
||||
#include "llvm/Assembly/PrintModulePass.h"
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
#include "llvm/ExecutionEngine/JIT.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/DynamicLibrary.h"
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "cling/Interpreter/StoredValueRef.h"
|
||||
#include "cling/Interpreter/ValuePrinter.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
|
||||
using namespace cling;
|
||||
using namespace clang;
|
||||
@ -15,9 +16,7 @@ using namespace llvm;
|
||||
StoredValueRef::StoredValue::StoredValue(const ASTContext& ctx,
|
||||
QualType clangTy,
|
||||
const llvm::Type* llvm_Ty)
|
||||
:m_Mem(0) {
|
||||
m_ClangType = clangTy;
|
||||
m_LLVMType = llvm_Ty;
|
||||
:Value(GenericValue(), clangTy, llvm_Ty), m_Mem(0) {
|
||||
if (!(clangTy->isIntegralOrEnumerationType()
|
||||
|| clangTy->isRealFloatingType()
|
||||
|| clangTy->hasPointerRepresentation())) {
|
||||
@ -25,7 +24,7 @@ StoredValueRef::StoredValue::StoredValue(const ASTContext& ctx,
|
||||
if (size > sizeof(m_Buf))
|
||||
m_Mem = new char[size];
|
||||
else m_Mem = m_Buf;
|
||||
m_GV = llvm::PTOGV(m_Mem);
|
||||
setGV(llvm::PTOGV(m_Mem));
|
||||
};
|
||||
}
|
||||
|
||||
@ -34,9 +33,9 @@ StoredValueRef::StoredValue::~StoredValue() {
|
||||
delete [] m_Mem;
|
||||
}
|
||||
|
||||
int64_t StoredValueRef::StoredValue::getAllocSizeInBytes(
|
||||
long long StoredValueRef::StoredValue::getAllocSizeInBytes(
|
||||
const ASTContext& ctx) const {
|
||||
return ctx.getTypeSizeInChars(m_ClangType).getQuantity();
|
||||
return (long long) ctx.getTypeSizeInChars(getClangType()).getQuantity();
|
||||
}
|
||||
|
||||
|
||||
|
107
lib/Interpreter/Value.cpp
Normal file
107
lib/Interpreter/Value.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// CLING - the C++ LLVM-based InterpreterG :)
|
||||
// version: $Id: Value.cpp 48537 2013-02-11 17:30:03Z vvassilev $
|
||||
// author: Axel Naumann <axel@cern.ch>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "cling/Interpreter/Value.h"
|
||||
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/CanonicalType.h"
|
||||
|
||||
namespace cling {
|
||||
|
||||
Value::Value(const llvm::GenericValue& v, clang::QualType t)
|
||||
: m_ClangType(t.getAsOpaquePtr()), m_LLVMType(0)
|
||||
{
|
||||
setGV(v);
|
||||
}
|
||||
|
||||
Value::Value(const llvm::GenericValue& v, clang::QualType clangTy,
|
||||
const llvm::Type* llvmTy)
|
||||
: m_ClangType(clangTy.getAsOpaquePtr()), m_LLVMType(llvmTy)
|
||||
{
|
||||
setGV(v);
|
||||
}
|
||||
|
||||
llvm::GenericValue Value::getGV() const {
|
||||
return reinterpret_cast<const llvm::GenericValue&>(m_GV);
|
||||
}
|
||||
void Value::setGV(llvm::GenericValue GV) {
|
||||
reinterpret_cast<llvm::GenericValue&>(m_GV) = GV;
|
||||
}
|
||||
|
||||
clang::QualType Value::getClangType() const {
|
||||
assert(sizeof(clang::QualType) <= sizeof(m_ClangType) && "m_ClangType too small!");
|
||||
return clang::QualType::getFromOpaquePtr(m_ClangType);
|
||||
}
|
||||
|
||||
bool Value::isValid() const { return !getClangType().isNull(); }
|
||||
|
||||
bool Value::isVoid(const clang::ASTContext& ASTContext) const {
|
||||
return isValid()
|
||||
&& getClangType().getDesugaredType(ASTContext)->isVoidType();
|
||||
}
|
||||
|
||||
Value::EStorageType Value::getStorageType() const {
|
||||
const clang::Type* desugCanon = getClangType()->getUnqualifiedDesugaredType();
|
||||
desugCanon = desugCanon->getCanonicalTypeUnqualified()->getTypePtr()
|
||||
->getUnqualifiedDesugaredType();
|
||||
if (desugCanon->isSignedIntegerOrEnumerationType())
|
||||
return kSignedIntegerOrEnumerationType;
|
||||
else if (desugCanon->isUnsignedIntegerOrEnumerationType())
|
||||
return kUnsignedIntegerOrEnumerationType;
|
||||
else if (desugCanon->isRealFloatingType()) {
|
||||
const clang::BuiltinType* BT = desugCanon->getAs<clang::BuiltinType>();
|
||||
if (BT->getKind() == clang::BuiltinType::Double)
|
||||
return kDoubleType;
|
||||
else if (BT->getKind() == clang::BuiltinType::Float)
|
||||
return kFloatType;
|
||||
else if (BT->getKind() == clang::BuiltinType::LongDouble)
|
||||
return kLongDoubleType;
|
||||
} else if (desugCanon->isPointerType() || desugCanon->isObjectType())
|
||||
return kPointerType;
|
||||
return kUnsupportedType;
|
||||
}
|
||||
|
||||
void* Value::getAs(void**) const { return getGV().PointerVal; }
|
||||
double Value::getAs(double*) const { return getGV().DoubleVal; }
|
||||
long double Value::getAs(long double*) const {
|
||||
return getAs((double*)0);
|
||||
}
|
||||
float Value::getAs(float*) const { return getGV().FloatVal; }
|
||||
bool Value::getAs(bool*) const { return getGV().IntVal.getBoolValue(); }
|
||||
signed char Value::getAs(signed char*) const {
|
||||
return (signed char) getAs((signed long long*)0);
|
||||
}
|
||||
unsigned char Value::getAs(unsigned char*) const {
|
||||
return (unsigned char) getAs((unsigned long long*)0);
|
||||
}
|
||||
signed short Value::getAs(signed short*) const {
|
||||
return (signed short) getAs((signed long long*)0);
|
||||
}
|
||||
unsigned short Value::getAs(unsigned short*) const {
|
||||
return (unsigned short) getAs((unsigned long long*)0);
|
||||
}
|
||||
signed int Value::getAs(signed int*) const {
|
||||
return (signed int) getAs((signed long long*)0);
|
||||
}
|
||||
unsigned int Value::getAs(unsigned int*) const {
|
||||
return (unsigned int) getAs((unsigned long long*)0);
|
||||
}
|
||||
signed long Value::getAs(signed long*) const {
|
||||
return (long) getAs((signed long long*)0);
|
||||
}
|
||||
unsigned long Value::getAs(unsigned long*) const {
|
||||
return (signed long) getAs((unsigned long long*)0);
|
||||
}
|
||||
signed long long Value::getAs(signed long long*) const {
|
||||
return getGV().IntVal.getSExtValue();
|
||||
}
|
||||
unsigned long long Value::getAs(unsigned long long*) const {
|
||||
return getGV().IntVal.getZExtValue();
|
||||
}
|
||||
|
||||
} // namespace cling
|
@ -18,6 +18,7 @@
|
||||
#include "clang/AST/Type.h"
|
||||
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
Loading…
Reference in New Issue
Block a user