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);
55 struct LocalPrintingPolicyRAII {
61 Context.setPrintingPolicy(PP);
63 ~LocalPrintingPolicyRAII() { Context.setPrintingPolicy(Policy); }
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>(Canon)) {
90 if (llvm::isa<SubstTemplateTypeParmType>(SSDesugar) ||
91 llvm::isa<TemplateSpecializationType>(SSDesugar))
100 llvm::raw_string_ostream SS(Str);
103 uint64_t
Data =
V.convertTo<uint64_t>();
107 auto *ED =
V.getType()->castAsEnumDecl();
108 for (
auto I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E; ++I) {
109 if (I->getInitVal() == AP) {
112 SS <<
"(" + I->getQualifiedNameAsString() <<
")";
117 AP.toString(APStr, 10);
124 llvm::raw_string_ostream SS(Str);
125 SS <<
"Function @" << Ptr;
127 const DeclContext *PTU =
V.getASTContext().getTranslationUnitDecl();
138 if (
auto *InterfaceCall = llvm::dyn_cast<CallExpr>(TLSD->
getStmt())) {
139 const auto *Arg = InterfaceCall->getArg( 3);
141 while (
const CastExpr *CastE = llvm::dyn_cast<CastExpr>(Arg))
142 Arg = CastE->getSubExpr();
143 if (
const DeclRefExpr *DeclRefExp = llvm::dyn_cast<DeclRefExpr>(Arg))
144 FD = llvm::dyn_cast<FunctionDecl>(DeclRefExp->getDecl());
158 llvm::raw_string_ostream SS(Str);
167 std::string Result =
"\"";
182std::string Interpreter::ValueDataToString(
const Value &
V)
const {
189 QualType ElemTy = CAT->getElementType();
196 char last = *(
char *)(((
uintptr_t)
V.getPtr()) + ElemCount * ElemSize - 1);
201 std::string
Result =
"{ ";
202 for (
unsigned Idx = 0, N = CAT->getZExtSize(); Idx < N; ++Idx) {
207 InnerV.
setRawBits((
void *)Offset, ElemSize * 8);
210 size_t Stride = ElemCount / N;
212 InnerV.
setPtr((
void *)Offset);
215 Result += ValueDataToString(InnerV);
236 auto formatFloating = [](
auto Val,
char Suffix =
'\0') -> std::string {
238 llvm::raw_string_ostream SS(Out);
241 SS << llvm::format(
"%g", Val);
244 if (Val ==
static_cast<decltype(Val)
>(
static_cast<int64_t>(Val)))
245 SS << llvm::format(
"%.1f", Val);
247 SS << llvm::format(
"%#.6g", Val);
248 else if (Suffix ==
'L')
249 SS << llvm::format(
"%#.12Lg", Val);
251 SS << llvm::format(
"%#.8g", Val);
259 llvm::raw_string_ostream SS(Str);
260 switch (BT->getKind()) {
262 return "{ error: unknown builtin type '" + std::to_string(BT->getKind()) +
264 case clang::BuiltinType::Bool:
265 SS << ((
V.getBool()) ?
"true" :
"false");
267 case clang::BuiltinType::Char_S:
268 SS <<
'\'' <<
V.getChar_S() <<
'\'';
270 case clang::BuiltinType::SChar:
271 SS <<
'\'' <<
V.getSChar() <<
'\'';
273 case clang::BuiltinType::Char_U:
274 SS <<
'\'' <<
V.getChar_U() <<
'\'';
276 case clang::BuiltinType::UChar:
277 SS <<
'\'' <<
V.getUChar() <<
'\'';
279 case clang::BuiltinType::Short:
282 case clang::BuiltinType::UShort:
285 case clang::BuiltinType::Int:
288 case clang::BuiltinType::UInt:
291 case clang::BuiltinType::Long:
294 case clang::BuiltinType::ULong:
297 case clang::BuiltinType::LongLong:
298 SS <<
V.getLongLong();
300 case clang::BuiltinType::ULongLong:
301 SS <<
V.getULongLong();
303 case clang::BuiltinType::Float:
304 return formatFloating(
V.getFloat(),
'f');
306 case clang::BuiltinType::Double:
307 return formatFloating(
V.getDouble());
309 case clang::BuiltinType::LongDouble:
310 return formatFloating(
V.getLongDouble(),
'L');
339std::string Interpreter::ValueTypeToString(
const Value &
V)
const {
340 ASTContext &Ctx =
const_cast<ASTContext &
>(
V.getASTContext());
341 QualType QT =
V.getType();
353 assert(CXXRD &&
"Cannot compile a destructor for a nullptr");
354 if (
auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end())
355 return Dtor->getSecond();
358 return llvm::orc::ExecutorAddr{};
360 CXXDestructorDecl *DtorRD =
363 llvm::StringRef Name =
364 Act->getCodeGen()->GetMangledName(GlobalDecl(DtorRD,
Dtor_Base));
367 return AddrOrErr.takeError();
369 Dtors[CXXRD] = *AddrOrErr;
376 :
public TypeVisitor<InterfaceKindVisitor, InterfaceKind> {
384 : S(S), E(E), Args(Args) {}
414 E->IgnoreImpCasts());
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; }));
489 auto LookupInterface = [&](Expr *&
Interface,
490 llvm::StringRef Name) -> llvm::Error {
491 LookupResult
R(S, &Ctx.
Idents.
get(Name), SourceLocation(),
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);
522 llvm::SmallVector<Expr *, 4> AdjustedArgs;
527 AdjustedArgs.push_back(
533 if (
auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E))
534 E = EWC->getSubExpr();
548 AdjustedArgs.push_back(TypeArg);
552 InterfaceKindVisitor
V(S, E, AdjustedArgs);
553 Scope *Scope =
nullptr;
565 return llvm::make_error<llvm::StringError>(
567 llvm::inconvertibleErrorCode());
574 Dtor->
addAttr(UsedAttr::CreateImplicit(Ctx));
589 Expr *Args[] = {E, AllocCall.
get(), ArrSizeExpr};
592 SourceLocation(), Args, SourceLocation());
594 return llvm::make_error<llvm::StringError>(
596 llvm::inconvertibleErrorCode());
602 true, SourceLocation(), Args,
604 SourceRange(), TSI->
getType(), TSI, std::nullopt,
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.
@ ForVisibleRedeclaration
The lookup results will be used for redeclaration of a name, if an entity by that name already exists...
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.
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++ struct/union/class.
bool hasIrrelevantDestructor() const
Determine whether this class has a destructor which has no semantic effect.
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
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.
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
A pointer to member type per C++ 8.3.3 - Pointers to members.
This represents a decl that may have a name.
std::string getQualifiedNameAsString() const
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
Base for LValueReferenceType and RValueReferenceType.
Sema - This implements semantic analysis and AST building for C.
@ 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.
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)
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.
bool isa(CodeGen::Address addr)
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)
U cast(CodeGen::Address addr)
static constexpr llvm::StringRef VPName[]
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
ActionResult< Expr * > ExprResult
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
__DEVICE__ bool isinf(float __x)
__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)