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>(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();
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);
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 {
341 ASTContext &Ctx =
const_cast<ASTContext &
>(
V.getASTContext());
342 QualType QT =
V.getType();
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{};
361 CXXDestructorDecl *DtorRD =
364 llvm::StringRef Name =
365 Act->getCodeGen()->GetMangledName(GlobalDecl(DtorRD,
Dtor_Base));
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; }));
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)