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) {
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);
434 HandleIntegralOrEnumType(Ty);
441 void HandleIntegralOrEnumType(
const Type *Ty) {
448 assert(!CastedExpr.
isInvalid() &&
"Cannot create cstyle cast expr");
449 Args.push_back(CastedExpr.
get());
452 void HandlePtrType(
const Type *Ty) {
457 assert(!CastedExpr.
isInvalid() &&
"Can not create cstyle cast expression");
458 Args.push_back(CastedExpr.
get());
462static constexpr llvm::StringRef
VPName[] = {
463 "__clang_Interpreter_SetValueNoAlloc",
464 "__clang_Interpreter_SetValueWithAlloc",
465 "__clang_Interpreter_SetValueCopyArr",
"__ci_newtag"};
485 if (!ValuePrintingInfo[0]) {
486 assert(llvm::all_of(ValuePrintingInfo, [](
Expr *E) {
return !E; }));
488 auto LookupInterface = [&](Expr *&
Interface,
489 llvm::StringRef Name) -> llvm::Error {
490 LookupResult
R(S, &Ctx.
Idents.
get(Name), SourceLocation(),
495 return llvm::make_error<llvm::StringError>(
496 Name +
" not found!", llvm::inconvertibleErrorCode());
500 return llvm::Error::success();
502 if (llvm::Error Err =
504 return std::move(Err);
506 if (llvm::Error Err =
508 return std::move(Err);
510 if (llvm::Error Err =
512 return std::move(Err);
515 if (llvm::Error Err =
517 return std::move(Err);
521 llvm::SmallVector<Expr *, 4> AdjustedArgs;
526 AdjustedArgs.push_back(
533 auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E);
535 E = EWC->getSubExpr();
549 AdjustedArgs.push_back(TypeArg);
553 InterfaceKindVisitor
V(S, E, AdjustedArgs);
554 Scope *Scope =
nullptr;
566 return llvm::make_error<llvm::StringError>(
568 llvm::inconvertibleErrorCode());
575 Dtor->addAttr(UsedAttr::CreateImplicit(Ctx));
590 Expr *Args[] = {E, AllocCall.
get(), ArrSizeExpr};
593 SourceLocation(), Args, SourceLocation());
595 return llvm::make_error<llvm::StringError>(
597 llvm::inconvertibleErrorCode());
603 true, SourceLocation(), Args,
605 SourceRange(), TSI->
getType(), TSI, std::nullopt,
609 return llvm::make_error<llvm::StringError>(
610 "Cannot build a call to placement new",
611 llvm::inconvertibleErrorCode());
630 llvm_unreachable(
"Unhandled InterfaceKind");
644 Ctx,
Result, EWC->cleanupsHaveSideEffects(), EWC->getObjects());
650using namespace clang;
667 VRef =
Value(I, OpaqueType);
675 if (VRef.
getKind() == Value::K_PtrOrObj) {
679 QT = ED->getIntegerType();
682 llvm_unreachable(
"unknown type kind!");
685 case BuiltinType::Bool:
686 VRef.setBool(
va_arg(args,
int));
688 case BuiltinType::Char_S:
689 VRef.setChar_S(
va_arg(args,
int));
691 case BuiltinType::SChar:
692 VRef.setSChar(
va_arg(args,
int));
694 case BuiltinType::Char_U:
695 VRef.setChar_U(
va_arg(args,
unsigned));
697 case BuiltinType::UChar:
698 VRef.setUChar(
va_arg(args,
unsigned));
700 case BuiltinType::Short:
701 VRef.setShort(
va_arg(args,
int));
703 case BuiltinType::UShort:
704 VRef.setUShort(
va_arg(args,
unsigned));
706 case BuiltinType::Int:
707 VRef.setInt(
va_arg(args,
int));
709 case BuiltinType::UInt:
710 VRef.setUInt(
va_arg(args,
unsigned));
712 case BuiltinType::Long:
713 VRef.setLong(
va_arg(args,
long));
715 case BuiltinType::ULong:
716 VRef.setULong(
va_arg(args,
unsigned long));
718 case BuiltinType::LongLong:
719 VRef.setLongLong(
va_arg(args,
long long));
721 case BuiltinType::ULongLong:
722 VRef.setULongLong(
va_arg(args,
unsigned long long));
725 case BuiltinType::Float:
726 VRef.setFloat(
va_arg(args,
double));
728 case BuiltinType::Double:
729 VRef.setDouble(
va_arg(args,
double));
731 case BuiltinType::LongDouble:
732 VRef.setLongDouble(
va_arg(args,
long double));
750 return operator new(__sz,
__p);
Defines the clang::ASTContext interface.
Result
Implement __builtin_bit_cast and related operations.
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.
static uint64_t getConstantArrayElementCount(const ConstantArrayType *CA)
Return number of (potentially nested) 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
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
static ExprWithCleanups * Create(const ASTContext &C, EmptyShell empty, unsigned numObjects)
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....
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
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 NBytes=sizeof(Storage))
Copy NBytes bytes from Ptr into the raw storage.
Top level wrappers for InstallAPI frontend operations.
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)