25#include "llvm/Support/Error.h"
26#include "llvm/Support/raw_ostream.h"
34#define DEBUG_TYPE "interp-value"
40 llvm::raw_string_ostream SS(Str);
43 SS <<
D->getQualifiedNameAsString();
55 struct LocalPrintingPolicyRAII {
68 if (
const auto *TTy = llvm::dyn_cast<TagType>(NonRefTy))
71 if (
const auto *TRy = dyn_cast<RecordType>(NonRefTy))
81 if (
const auto *TDTy = dyn_cast<TypedefType>(NonRefTy)) {
90 if (llvm::isa<SubstTemplateTypeParmType>(SSDesugar))
92 else if (llvm::isa<TemplateSpecializationType>(SSDesugar))
101 llvm::raw_string_ostream SS(Str);
104 uint64_t
Data =
V.convertTo<uint64_t>();
108 auto *ED =
V.getType()->castAsEnumDecl();
109 for (
auto I = ED->enumerator_begin(),
E = ED->enumerator_end(); I !=
E; ++I) {
110 if (I->getInitVal() == AP) {
113 SS <<
"(" + I->getQualifiedNameAsString() <<
")";
118 AP.toString(APStr, 10);
125 llvm::raw_string_ostream SS(Str);
126 SS <<
"Function @" << Ptr;
128 const DeclContext *PTU =
V.getASTContext().getTranslationUnitDecl();
133 if (isa<TopLevelStmtDecl>(
D))
134 TLSD = cast<TopLevelStmtDecl>(
D);
139 if (
auto *InterfaceCall = llvm::dyn_cast<CallExpr>(TLSD->
getStmt())) {
140 const auto *Arg = InterfaceCall->getArg( 3);
142 while (
const CastExpr *CastE = llvm::dyn_cast<CastExpr>(Arg))
143 Arg = CastE->getSubExpr();
144 if (
const DeclRefExpr *DeclRefExp = llvm::dyn_cast<DeclRefExpr>(Arg))
145 FD = llvm::dyn_cast<FunctionDecl>(DeclRefExp->getDecl());
159 llvm::raw_string_ostream SS(Str);
168 std::string Result =
"\"";
183std::string Interpreter::ValueDataToString(
const Value &
V)
const {
190 QualType ElemTy = CAT->getElementType();
197 char last = *(
char *)(((
uintptr_t)
V.getPtr()) + ElemCount * ElemSize - 1);
202 std::string
Result =
"{ ";
203 for (
unsigned Idx = 0, N = CAT->getZExtSize(); Idx < N; ++Idx) {
208 InnerV.
setRawBits((
void *)Offset, ElemSize * 8);
211 size_t Stride = ElemCount / N;
213 InnerV.
setPtr((
void *)Offset);
216 Result += ValueDataToString(InnerV);
237 auto formatFloating = [](
auto Val,
char Suffix =
'\0') -> std::string {
239 llvm::raw_string_ostream SS(Out);
241 if (std::isnan(Val) || std::isinf(Val)) {
242 SS << llvm::format(
"%g", Val);
245 if (Val ==
static_cast<decltype(Val)
>(
static_cast<int64_t>(Val)))
246 SS << llvm::format(
"%.1f", Val);
248 SS << llvm::format(
"%#.6g", Val);
249 else if (Suffix ==
'L')
250 SS << llvm::format(
"%#.12Lg", Val);
252 SS << llvm::format(
"%#.8g", Val);
260 llvm::raw_string_ostream SS(Str);
261 switch (BT->getKind()) {
263 return "{ error: unknown builtin type '" + std::to_string(BT->getKind()) +
265 case clang::BuiltinType::Bool:
266 SS << ((
V.getBool()) ?
"true" :
"false");
268 case clang::BuiltinType::Char_S:
269 SS <<
'\'' <<
V.getChar_S() <<
'\'';
271 case clang::BuiltinType::SChar:
272 SS <<
'\'' <<
V.getSChar() <<
'\'';
274 case clang::BuiltinType::Char_U:
275 SS <<
'\'' <<
V.getChar_U() <<
'\'';
277 case clang::BuiltinType::UChar:
278 SS <<
'\'' <<
V.getUChar() <<
'\'';
280 case clang::BuiltinType::Short:
283 case clang::BuiltinType::UShort:
286 case clang::BuiltinType::Int:
289 case clang::BuiltinType::UInt:
292 case clang::BuiltinType::Long:
295 case clang::BuiltinType::ULong:
298 case clang::BuiltinType::LongLong:
299 SS <<
V.getLongLong();
301 case clang::BuiltinType::ULongLong:
302 SS <<
V.getULongLong();
304 case clang::BuiltinType::Float:
305 return formatFloating(
V.getFloat(),
'f');
307 case clang::BuiltinType::Double:
308 return formatFloating(
V.getDouble());
310 case clang::BuiltinType::LongDouble:
311 return formatFloating(
V.getLongDouble(),
'L');
340std::string Interpreter::ValueTypeToString(
const Value &
V)
const {
354 assert(CXXRD &&
"Cannot compile a destructor for a nullptr");
355 if (
auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end())
356 return Dtor->getSecond();
359 return llvm::orc::ExecutorAddr{};
364 llvm::StringRef Name =
368 return AddrOrErr.takeError();
370 Dtors[CXXRD] = *AddrOrErr;
377 :
public TypeVisitor<InterfaceKindVisitor, InterfaceKind> {
385 : S(S),
E(
E), Args(Args) {}
415 assert(!AddrOfE.
isInvalid() &&
"Can not create unary expression");
416 Args.push_back(AddrOfE.
get());
426 HandleIntegralOrEnumType(Ty);
435 HandleIntegralOrEnumType(Ty);
442 void HandleIntegralOrEnumType(
const Type *Ty) {
449 assert(!CastedExpr.
isInvalid() &&
"Cannot create cstyle cast expr");
450 Args.push_back(CastedExpr.
get());
453 void HandlePtrType(
const Type *Ty) {
458 assert(!CastedExpr.
isInvalid() &&
"Can not create cstyle cast expression");
459 Args.push_back(CastedExpr.
get());
463static constexpr llvm::StringRef
VPName[] = {
464 "__clang_Interpreter_SetValueNoAlloc",
465 "__clang_Interpreter_SetValueWithAlloc",
466 "__clang_Interpreter_SetValueCopyArr",
"__ci_newtag"};
486 if (!ValuePrintingInfo[0]) {
487 assert(llvm::all_of(ValuePrintingInfo, [](
Expr *
E) {
return !
E; }));
490 llvm::StringRef Name) -> llvm::Error {
493 RedeclarationKind::ForVisibleRedeclaration);
496 return llvm::make_error<llvm::StringError>(
497 Name +
" not found!", llvm::inconvertibleErrorCode());
501 return llvm::Error::success();
503 if (llvm::Error Err =
505 return std::move(Err);
507 if (llvm::Error Err =
509 return std::move(Err);
511 if (llvm::Error Err =
513 return std::move(Err);
516 if (llvm::Error Err =
518 return std::move(Err);
527 AdjustedArgs.push_back(
533 if (
auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(
E))
534 E = EWC->getSubExpr();
548 AdjustedArgs.push_back(TypeArg);
565 return llvm::make_error<llvm::StringError>(
567 llvm::inconvertibleErrorCode());
574 Dtor->
addAttr(UsedAttr::CreateImplicit(Ctx));
581 const auto *CATy = cast<ConstantArrayType>(DesugaredTy.
getTypePtr());
589 Expr *Args[] = {
E, AllocCall.
get(), ArrSizeExpr};
594 return llvm::make_error<llvm::StringError>(
596 llvm::inconvertibleErrorCode());
608 return llvm::make_error<llvm::StringError>(
609 "Cannot build a call to placement new",
610 llvm::inconvertibleErrorCode());
624 llvm_unreachable(
"Unhandled InterfaceKind");
631 return SetValueE.
get();
636using namespace clang;
653 VRef =
Value(I, OpaqueType);
665 QT = ED->getIntegerType();
668 llvm_unreachable(
"unknown type kind!");
671 case BuiltinType::Bool:
672 VRef.setBool(
va_arg(args,
int));
674 case BuiltinType::Char_S:
675 VRef.setChar_S(
va_arg(args,
int));
677 case BuiltinType::SChar:
678 VRef.setSChar(
va_arg(args,
int));
680 case BuiltinType::Char_U:
681 VRef.setChar_U(
va_arg(args,
unsigned));
683 case BuiltinType::UChar:
684 VRef.setUChar(
va_arg(args,
unsigned));
686 case BuiltinType::Short:
687 VRef.setShort(
va_arg(args,
int));
689 case BuiltinType::UShort:
690 VRef.setUShort(
va_arg(args,
unsigned));
692 case BuiltinType::Int:
693 VRef.setInt(
va_arg(args,
int));
695 case BuiltinType::UInt:
696 VRef.setUInt(
va_arg(args,
unsigned));
698 case BuiltinType::Long:
699 VRef.setLong(
va_arg(args,
long));
701 case BuiltinType::ULong:
702 VRef.setULong(
va_arg(args,
unsigned long));
704 case BuiltinType::LongLong:
705 VRef.setLongLong(
va_arg(args,
long long));
707 case BuiltinType::ULongLong:
708 VRef.setULongLong(
va_arg(args,
unsigned long long));
711 case BuiltinType::Float:
712 VRef.setFloat(
va_arg(args,
double));
714 case BuiltinType::Double:
715 VRef.setDouble(
va_arg(args,
double));
717 case BuiltinType::LongDouble:
718 VRef.setLongDouble(
va_arg(args,
long double));
736 return operator new(__sz,
__p);
Defines the clang::ASTContext interface.
static std::string EnumToString(const Value &V)
static std::string QualTypeToString(ASTContext &Ctx, QualType QT)
REPL_EXTERNAL_VISIBILITY void * __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, void *OpaqueType)
static std::string FunctionToString(const Value &V, const void *Ptr)
static std::string VoidPtrToString(const void *Ptr)
REPL_EXTERNAL_VISIBILITY void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,...)
static std::string DeclTypeToString(const QualType &QT, NamedDecl *D)
static std::string CharPtrToString(const char *Ptr)
#define REPL_EXTERNAL_VISIBILITY
Defines the clang::Preprocessor interface.
C Language Family Type Representation.
#define va_start(ap, param)
__builtin_va_list va_list
static __inline__ uint32_t volatile uint32_t * __p
a trap message and trap category.
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TranslationUnitDecl * getTranslationUnitDecl() const
const ConstantArrayType * getAsConstantArrayType(QualType T) const
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
const LangOptions & getLangOpts() const
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
const clang::PrintingPolicy & getPrintingPolicy() const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const
Make an APSInt of the appropriate width and signedness for the given Value and integer Type.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
void setPrintingPolicy(const clang::PrintingPolicy &Policy)
QualType getBitIntType(bool Unsigned, unsigned NumBits) const
Return a bit-precise integer type with the specified signedness and bit count.
This class is used for builtin types like 'int'.
Represents a C++ destructor within a class.
Represents a C++ struct/union/class.
bool hasIrrelevantDestructor() const
Determine whether this class has a destructor which has no semantic effect.
Represents a C++ nested-name-specifier or a global scope specifier.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
ASTConsumer & getASTConsumer() const
Represents the canonical version of C arrays with a specified constant size.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
decl_range noload_decls() const
noload_decls_begin/end - Iterate over the declarations stored in this context that are currently load...
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
This represents one expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Represents a function declaration or definition.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
FunctionType - C99 6.7.5.3 - Function Declarators.
GlobalDecl - represents a global declaration.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
InterfaceKind VisitConstantArrayType(const ConstantArrayType *Ty)
InterfaceKind computeInterfaceKind(QualType Ty)
InterfaceKind VisitReferenceType(const ReferenceType *Ty)
InterfaceKind VisitPointerType(const PointerType *Ty)
InterfaceKind VisitEnumType(const EnumType *Ty)
InterfaceKind VisitBuiltinType(const BuiltinType *Ty)
InterfaceKind VisitFunctionType(const FunctionType *Ty)
InterfaceKind VisitRecordType(const RecordType *Ty)
InterfaceKind VisitMemberPointerType(const MemberPointerType *Ty)
InterfaceKindVisitor(Sema &S, Expr *E, llvm::SmallVectorImpl< Expr * > &Args)
Provides top-level interfaces for incremental compilation and execution.
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddress(GlobalDecl GD) const
const CompilerInstance * getCompilerInstance() const
Represents the results of name lookup.
A pointer to member type per C++ 8.3.3 - Pointers to members.
This represents a decl that may have a name.
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool hasQualifiers() const
Determine whether this type has any qualifiers.
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
void * getAsOpaquePtr() const
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
std::string getAsString() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Base for LValueReferenceType and RValueReferenceType.
Scope - A scope is a transient data structure that is used while parsing the program.
Sema - This implements semantic analysis and AST building for C.
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
ASTContext & getASTContext() const
CXXDestructorDecl * LookupDestructor(CXXRecordDecl *Class)
Look for the destructor of the given class.
ExprResult BuildCXXNew(SourceRange Range, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, QualType AllocType, TypeSourceInfo *AllocTypeInfo, std::optional< Expr * > ArraySize, SourceRange DirectInitRange, Expr *Initializer)
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl=false)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr)
ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEndLoc() const LLVM_READONLY
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
A declaration that models statements at global scope.
A container of type source information.
QualType getType() const
Return the type wrapped by this type source info.
InterfaceKind Visit(const Type *T)
Performs the operation associated with this visitor object.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
QualType getLocallyUnqualifiedSingleStepDesugaredType() const
Pull a single level of sugar off of this locally-unqualified type.
bool isFunctionPointerType() const
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isEnumeralType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isBuiltinType() const
Helper methods to distinguish type categories.
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
bool isMemberPointerType() const
bool isFunctionProtoType() const
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
bool isFunctionType() const
bool isFloatingType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
bool isRecordType() const
void setRawBits(void *Ptr, unsigned NBits=sizeof(Storage))
The JSON file list parser is used to communicate input to InstallAPI.
std::string GetFullTypeName(ASTContext &Ctx, QualType QT)
@ Result
The result type of a method or function.
IntegerLiteral * IntegerLiteralExpr(ASTContext &C, uint64_t Val)
@ Dtor_Base
Base object dtor.
Expr * CStyleCastPtrExpr(Sema &S, QualType Ty, Expr *E)
static constexpr llvm::StringRef VPName[]
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
Describes how types, statements, expressions, and declarations should be printed.
unsigned SuppressUnwrittenScope
Suppress printing parts of scope specifiers that are never written, e.g., for anonymous namespaces.
unsigned SuppressDefaultTemplateArgs
When true, attempt to suppress template arguments that match the default argument for the parameter.
unsigned SplitTemplateClosers
Whether nested templates must be closed like 'a<b<c> >' rather than 'a<b<c>>'.
ValueRef(const Interpreter *In, void *Ty)