1*a72d7eeaSVassil Vassilev //===--- InterpreterValuePrinter.cpp - Value printing utils -----*- C++ -*-===// 2*a72d7eeaSVassil Vassilev // 3*a72d7eeaSVassil Vassilev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*a72d7eeaSVassil Vassilev // See https://llvm.org/LICENSE.txt for license information. 5*a72d7eeaSVassil Vassilev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*a72d7eeaSVassil Vassilev // 7*a72d7eeaSVassil Vassilev //===----------------------------------------------------------------------===// 8*a72d7eeaSVassil Vassilev // 9*a72d7eeaSVassil Vassilev // This file implements routines for in-process value printing in clang-repl. 10*a72d7eeaSVassil Vassilev // 11*a72d7eeaSVassil Vassilev //===----------------------------------------------------------------------===// 12*a72d7eeaSVassil Vassilev 13*a72d7eeaSVassil Vassilev #include "IncrementalParser.h" 14*a72d7eeaSVassil Vassilev #include "InterpreterUtils.h" 15*a72d7eeaSVassil Vassilev #include "clang/AST/ASTContext.h" 16*a72d7eeaSVassil Vassilev #include "clang/AST/PrettyPrinter.h" 17*a72d7eeaSVassil Vassilev #include "clang/AST/Type.h" 18*a72d7eeaSVassil Vassilev #include "clang/Frontend/CompilerInstance.h" 19*a72d7eeaSVassil Vassilev #include "clang/Interpreter/Interpreter.h" 20*a72d7eeaSVassil Vassilev #include "clang/Interpreter/Value.h" 21*a72d7eeaSVassil Vassilev #include "clang/Lex/Preprocessor.h" 22*a72d7eeaSVassil Vassilev #include "clang/Sema/Lookup.h" 23*a72d7eeaSVassil Vassilev #include "clang/Sema/Sema.h" 24*a72d7eeaSVassil Vassilev 25*a72d7eeaSVassil Vassilev #include "llvm/Support/Error.h" 26*a72d7eeaSVassil Vassilev #include "llvm/Support/raw_ostream.h" 27*a72d7eeaSVassil Vassilev 28*a72d7eeaSVassil Vassilev #include <cassert> 29*a72d7eeaSVassil Vassilev #include <string> 30*a72d7eeaSVassil Vassilev 31*a72d7eeaSVassil Vassilev #include <cstdarg> 32*a72d7eeaSVassil Vassilev 33*a72d7eeaSVassil Vassilev namespace clang { 34*a72d7eeaSVassil Vassilev 35*a72d7eeaSVassil Vassilev llvm::Expected<llvm::orc::ExecutorAddr> 36*a72d7eeaSVassil Vassilev Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) { 37*a72d7eeaSVassil Vassilev assert(CXXRD && "Cannot compile a destructor for a nullptr"); 38*a72d7eeaSVassil Vassilev if (auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end()) 39*a72d7eeaSVassil Vassilev return Dtor->getSecond(); 40*a72d7eeaSVassil Vassilev 41*a72d7eeaSVassil Vassilev if (CXXRD->hasIrrelevantDestructor()) 42*a72d7eeaSVassil Vassilev return llvm::orc::ExecutorAddr{}; 43*a72d7eeaSVassil Vassilev 44*a72d7eeaSVassil Vassilev CXXDestructorDecl *DtorRD = 45*a72d7eeaSVassil Vassilev getCompilerInstance()->getSema().LookupDestructor(CXXRD); 46*a72d7eeaSVassil Vassilev 47*a72d7eeaSVassil Vassilev llvm::StringRef Name = 48*a72d7eeaSVassil Vassilev getCodeGen()->GetMangledName(GlobalDecl(DtorRD, Dtor_Base)); 49*a72d7eeaSVassil Vassilev auto AddrOrErr = getSymbolAddress(Name); 50*a72d7eeaSVassil Vassilev if (!AddrOrErr) 51*a72d7eeaSVassil Vassilev return AddrOrErr.takeError(); 52*a72d7eeaSVassil Vassilev 53*a72d7eeaSVassil Vassilev Dtors[CXXRD] = *AddrOrErr; 54*a72d7eeaSVassil Vassilev return AddrOrErr; 55*a72d7eeaSVassil Vassilev } 56*a72d7eeaSVassil Vassilev 57*a72d7eeaSVassil Vassilev enum InterfaceKind { NoAlloc, WithAlloc, CopyArray, NewTag }; 58*a72d7eeaSVassil Vassilev 59*a72d7eeaSVassil Vassilev class InterfaceKindVisitor 60*a72d7eeaSVassil Vassilev : public TypeVisitor<InterfaceKindVisitor, InterfaceKind> { 61*a72d7eeaSVassil Vassilev 62*a72d7eeaSVassil Vassilev Sema &S; 63*a72d7eeaSVassil Vassilev Expr *E; 64*a72d7eeaSVassil Vassilev llvm::SmallVectorImpl<Expr *> &Args; 65*a72d7eeaSVassil Vassilev 66*a72d7eeaSVassil Vassilev public: 67*a72d7eeaSVassil Vassilev InterfaceKindVisitor(Sema &S, Expr *E, llvm::SmallVectorImpl<Expr *> &Args) 68*a72d7eeaSVassil Vassilev : S(S), E(E), Args(Args) {} 69*a72d7eeaSVassil Vassilev 70*a72d7eeaSVassil Vassilev InterfaceKind computeInterfaceKind(QualType Ty) { 71*a72d7eeaSVassil Vassilev return Visit(Ty.getTypePtr()); 72*a72d7eeaSVassil Vassilev } 73*a72d7eeaSVassil Vassilev 74*a72d7eeaSVassil Vassilev InterfaceKind VisitRecordType(const RecordType *Ty) { 75*a72d7eeaSVassil Vassilev return InterfaceKind::WithAlloc; 76*a72d7eeaSVassil Vassilev } 77*a72d7eeaSVassil Vassilev 78*a72d7eeaSVassil Vassilev InterfaceKind VisitMemberPointerType(const MemberPointerType *Ty) { 79*a72d7eeaSVassil Vassilev return InterfaceKind::WithAlloc; 80*a72d7eeaSVassil Vassilev } 81*a72d7eeaSVassil Vassilev 82*a72d7eeaSVassil Vassilev InterfaceKind VisitConstantArrayType(const ConstantArrayType *Ty) { 83*a72d7eeaSVassil Vassilev return InterfaceKind::CopyArray; 84*a72d7eeaSVassil Vassilev } 85*a72d7eeaSVassil Vassilev 86*a72d7eeaSVassil Vassilev InterfaceKind VisitFunctionProtoType(const FunctionProtoType *Ty) { 87*a72d7eeaSVassil Vassilev HandlePtrType(Ty); 88*a72d7eeaSVassil Vassilev return InterfaceKind::NoAlloc; 89*a72d7eeaSVassil Vassilev } 90*a72d7eeaSVassil Vassilev 91*a72d7eeaSVassil Vassilev InterfaceKind VisitPointerType(const PointerType *Ty) { 92*a72d7eeaSVassil Vassilev HandlePtrType(Ty); 93*a72d7eeaSVassil Vassilev return InterfaceKind::NoAlloc; 94*a72d7eeaSVassil Vassilev } 95*a72d7eeaSVassil Vassilev 96*a72d7eeaSVassil Vassilev InterfaceKind VisitReferenceType(const ReferenceType *Ty) { 97*a72d7eeaSVassil Vassilev ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, E); 98*a72d7eeaSVassil Vassilev assert(!AddrOfE.isInvalid() && "Can not create unary expression"); 99*a72d7eeaSVassil Vassilev Args.push_back(AddrOfE.get()); 100*a72d7eeaSVassil Vassilev return InterfaceKind::NoAlloc; 101*a72d7eeaSVassil Vassilev } 102*a72d7eeaSVassil Vassilev 103*a72d7eeaSVassil Vassilev InterfaceKind VisitBuiltinType(const BuiltinType *Ty) { 104*a72d7eeaSVassil Vassilev if (Ty->isNullPtrType()) 105*a72d7eeaSVassil Vassilev Args.push_back(E); 106*a72d7eeaSVassil Vassilev else if (Ty->isFloatingType()) 107*a72d7eeaSVassil Vassilev Args.push_back(E); 108*a72d7eeaSVassil Vassilev else if (Ty->isIntegralOrEnumerationType()) 109*a72d7eeaSVassil Vassilev HandleIntegralOrEnumType(Ty); 110*a72d7eeaSVassil Vassilev else if (Ty->isVoidType()) { 111*a72d7eeaSVassil Vassilev // Do we need to still run `E`? 112*a72d7eeaSVassil Vassilev } 113*a72d7eeaSVassil Vassilev 114*a72d7eeaSVassil Vassilev return InterfaceKind::NoAlloc; 115*a72d7eeaSVassil Vassilev } 116*a72d7eeaSVassil Vassilev 117*a72d7eeaSVassil Vassilev InterfaceKind VisitEnumType(const EnumType *Ty) { 118*a72d7eeaSVassil Vassilev HandleIntegralOrEnumType(Ty); 119*a72d7eeaSVassil Vassilev return InterfaceKind::NoAlloc; 120*a72d7eeaSVassil Vassilev } 121*a72d7eeaSVassil Vassilev 122*a72d7eeaSVassil Vassilev private: 123*a72d7eeaSVassil Vassilev // Force cast these types to the uint that fits the register size. That way we 124*a72d7eeaSVassil Vassilev // reduce the number of overloads of `__clang_Interpreter_SetValueNoAlloc`. 125*a72d7eeaSVassil Vassilev void HandleIntegralOrEnumType(const Type *Ty) { 126*a72d7eeaSVassil Vassilev ASTContext &Ctx = S.getASTContext(); 127*a72d7eeaSVassil Vassilev uint64_t PtrBits = Ctx.getTypeSize(Ctx.VoidPtrTy); 128*a72d7eeaSVassil Vassilev QualType UIntTy = Ctx.getBitIntType(/*Unsigned=*/true, PtrBits); 129*a72d7eeaSVassil Vassilev TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(UIntTy); 130*a72d7eeaSVassil Vassilev ExprResult CastedExpr = 131*a72d7eeaSVassil Vassilev S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E); 132*a72d7eeaSVassil Vassilev assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr"); 133*a72d7eeaSVassil Vassilev Args.push_back(CastedExpr.get()); 134*a72d7eeaSVassil Vassilev } 135*a72d7eeaSVassil Vassilev 136*a72d7eeaSVassil Vassilev void HandlePtrType(const Type *Ty) { 137*a72d7eeaSVassil Vassilev ASTContext &Ctx = S.getASTContext(); 138*a72d7eeaSVassil Vassilev TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ctx.VoidPtrTy); 139*a72d7eeaSVassil Vassilev ExprResult CastedExpr = 140*a72d7eeaSVassil Vassilev S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E); 141*a72d7eeaSVassil Vassilev assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression"); 142*a72d7eeaSVassil Vassilev Args.push_back(CastedExpr.get()); 143*a72d7eeaSVassil Vassilev } 144*a72d7eeaSVassil Vassilev }; 145*a72d7eeaSVassil Vassilev 146*a72d7eeaSVassil Vassilev // This synthesizes a call expression to a speciall 147*a72d7eeaSVassil Vassilev // function that is responsible for generating the Value. 148*a72d7eeaSVassil Vassilev // In general, we transform: 149*a72d7eeaSVassil Vassilev // clang-repl> x 150*a72d7eeaSVassil Vassilev // To: 151*a72d7eeaSVassil Vassilev // // 1. If x is a built-in type like int, float. 152*a72d7eeaSVassil Vassilev // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x); 153*a72d7eeaSVassil Vassilev // // 2. If x is a struct, and a lvalue. 154*a72d7eeaSVassil Vassilev // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, 155*a72d7eeaSVassil Vassilev // &x); 156*a72d7eeaSVassil Vassilev // // 3. If x is a struct, but a rvalue. 157*a72d7eeaSVassil Vassilev // new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue, 158*a72d7eeaSVassil Vassilev // xQualType)) (x); 159*a72d7eeaSVassil Vassilev llvm::Expected<Expr *> Interpreter::ExtractValueFromExpr(Expr *E) { 160*a72d7eeaSVassil Vassilev Sema &S = getCompilerInstance()->getSema(); 161*a72d7eeaSVassil Vassilev ASTContext &Ctx = S.getASTContext(); 162*a72d7eeaSVassil Vassilev 163*a72d7eeaSVassil Vassilev // Find the value printing builtins. 164*a72d7eeaSVassil Vassilev if (!ValuePrintingInfo[0]) { 165*a72d7eeaSVassil Vassilev assert(llvm::all_of(ValuePrintingInfo, [](Expr *E) { return !E; })); 166*a72d7eeaSVassil Vassilev 167*a72d7eeaSVassil Vassilev auto LookupInterface = [&](Expr *&Interface, 168*a72d7eeaSVassil Vassilev llvm::StringRef Name) -> llvm::Error { 169*a72d7eeaSVassil Vassilev LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(), 170*a72d7eeaSVassil Vassilev Sema::LookupOrdinaryName, 171*a72d7eeaSVassil Vassilev RedeclarationKind::ForVisibleRedeclaration); 172*a72d7eeaSVassil Vassilev S.LookupQualifiedName(R, Ctx.getTranslationUnitDecl()); 173*a72d7eeaSVassil Vassilev if (R.empty()) 174*a72d7eeaSVassil Vassilev return llvm::make_error<llvm::StringError>( 175*a72d7eeaSVassil Vassilev Name + " not found!", llvm::inconvertibleErrorCode()); 176*a72d7eeaSVassil Vassilev 177*a72d7eeaSVassil Vassilev CXXScopeSpec CSS; 178*a72d7eeaSVassil Vassilev Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get(); 179*a72d7eeaSVassil Vassilev return llvm::Error::success(); 180*a72d7eeaSVassil Vassilev }; 181*a72d7eeaSVassil Vassilev static constexpr llvm::StringRef Builtin[] = { 182*a72d7eeaSVassil Vassilev "__clang_Interpreter_SetValueNoAlloc", 183*a72d7eeaSVassil Vassilev "__clang_Interpreter_SetValueWithAlloc", 184*a72d7eeaSVassil Vassilev "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"}; 185*a72d7eeaSVassil Vassilev if (llvm::Error Err = 186*a72d7eeaSVassil Vassilev LookupInterface(ValuePrintingInfo[NoAlloc], Builtin[NoAlloc])) 187*a72d7eeaSVassil Vassilev return std::move(Err); 188*a72d7eeaSVassil Vassilev 189*a72d7eeaSVassil Vassilev if (Ctx.getLangOpts().CPlusPlus) { 190*a72d7eeaSVassil Vassilev if (llvm::Error Err = 191*a72d7eeaSVassil Vassilev LookupInterface(ValuePrintingInfo[WithAlloc], Builtin[WithAlloc])) 192*a72d7eeaSVassil Vassilev return std::move(Err); 193*a72d7eeaSVassil Vassilev if (llvm::Error Err = 194*a72d7eeaSVassil Vassilev LookupInterface(ValuePrintingInfo[CopyArray], Builtin[CopyArray])) 195*a72d7eeaSVassil Vassilev return std::move(Err); 196*a72d7eeaSVassil Vassilev if (llvm::Error Err = 197*a72d7eeaSVassil Vassilev LookupInterface(ValuePrintingInfo[NewTag], Builtin[NewTag])) 198*a72d7eeaSVassil Vassilev return std::move(Err); 199*a72d7eeaSVassil Vassilev } 200*a72d7eeaSVassil Vassilev } 201*a72d7eeaSVassil Vassilev 202*a72d7eeaSVassil Vassilev llvm::SmallVector<Expr *, 4> AdjustedArgs; 203*a72d7eeaSVassil Vassilev // Create parameter `ThisInterp`. 204*a72d7eeaSVassil Vassilev AdjustedArgs.push_back(CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this)); 205*a72d7eeaSVassil Vassilev 206*a72d7eeaSVassil Vassilev // Create parameter `OutVal`. 207*a72d7eeaSVassil Vassilev AdjustedArgs.push_back( 208*a72d7eeaSVassil Vassilev CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue)); 209*a72d7eeaSVassil Vassilev 210*a72d7eeaSVassil Vassilev // Build `__clang_Interpreter_SetValue*` call. 211*a72d7eeaSVassil Vassilev 212*a72d7eeaSVassil Vassilev // Get rid of ExprWithCleanups. 213*a72d7eeaSVassil Vassilev if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E)) 214*a72d7eeaSVassil Vassilev E = EWC->getSubExpr(); 215*a72d7eeaSVassil Vassilev 216*a72d7eeaSVassil Vassilev QualType Ty = E->getType(); 217*a72d7eeaSVassil Vassilev QualType DesugaredTy = Ty.getDesugaredType(Ctx); 218*a72d7eeaSVassil Vassilev 219*a72d7eeaSVassil Vassilev // For lvalue struct, we treat it as a reference. 220*a72d7eeaSVassil Vassilev if (DesugaredTy->isRecordType() && E->isLValue()) { 221*a72d7eeaSVassil Vassilev DesugaredTy = Ctx.getLValueReferenceType(DesugaredTy); 222*a72d7eeaSVassil Vassilev Ty = Ctx.getLValueReferenceType(Ty); 223*a72d7eeaSVassil Vassilev } 224*a72d7eeaSVassil Vassilev 225*a72d7eeaSVassil Vassilev Expr *TypeArg = 226*a72d7eeaSVassil Vassilev CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)Ty.getAsOpaquePtr()); 227*a72d7eeaSVassil Vassilev // The QualType parameter `OpaqueType`, represented as `void*`. 228*a72d7eeaSVassil Vassilev AdjustedArgs.push_back(TypeArg); 229*a72d7eeaSVassil Vassilev 230*a72d7eeaSVassil Vassilev // We push the last parameter based on the type of the Expr. Note we need 231*a72d7eeaSVassil Vassilev // special care for rvalue struct. 232*a72d7eeaSVassil Vassilev InterfaceKindVisitor V(S, E, AdjustedArgs); 233*a72d7eeaSVassil Vassilev Scope *Scope = nullptr; 234*a72d7eeaSVassil Vassilev ExprResult SetValueE; 235*a72d7eeaSVassil Vassilev InterfaceKind Kind = V.computeInterfaceKind(DesugaredTy); 236*a72d7eeaSVassil Vassilev switch (Kind) { 237*a72d7eeaSVassil Vassilev case InterfaceKind::WithAlloc: 238*a72d7eeaSVassil Vassilev LLVM_FALLTHROUGH; 239*a72d7eeaSVassil Vassilev case InterfaceKind::CopyArray: { 240*a72d7eeaSVassil Vassilev // __clang_Interpreter_SetValueWithAlloc. 241*a72d7eeaSVassil Vassilev ExprResult AllocCall = 242*a72d7eeaSVassil Vassilev S.ActOnCallExpr(Scope, ValuePrintingInfo[InterfaceKind::WithAlloc], 243*a72d7eeaSVassil Vassilev E->getBeginLoc(), AdjustedArgs, E->getEndLoc()); 244*a72d7eeaSVassil Vassilev assert(!AllocCall.isInvalid() && "Can't create runtime interface call!"); 245*a72d7eeaSVassil Vassilev 246*a72d7eeaSVassil Vassilev TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation()); 247*a72d7eeaSVassil Vassilev 248*a72d7eeaSVassil Vassilev // Force CodeGen to emit destructor. 249*a72d7eeaSVassil Vassilev if (auto *RD = Ty->getAsCXXRecordDecl()) { 250*a72d7eeaSVassil Vassilev auto *Dtor = S.LookupDestructor(RD); 251*a72d7eeaSVassil Vassilev Dtor->addAttr(UsedAttr::CreateImplicit(Ctx)); 252*a72d7eeaSVassil Vassilev getCompilerInstance()->getASTConsumer().HandleTopLevelDecl( 253*a72d7eeaSVassil Vassilev DeclGroupRef(Dtor)); 254*a72d7eeaSVassil Vassilev } 255*a72d7eeaSVassil Vassilev 256*a72d7eeaSVassil Vassilev // __clang_Interpreter_SetValueCopyArr. 257*a72d7eeaSVassil Vassilev if (Kind == InterfaceKind::CopyArray) { 258*a72d7eeaSVassil Vassilev const auto *ConstantArrTy = 259*a72d7eeaSVassil Vassilev cast<ConstantArrayType>(DesugaredTy.getTypePtr()); 260*a72d7eeaSVassil Vassilev size_t ArrSize = Ctx.getConstantArrayElementCount(ConstantArrTy); 261*a72d7eeaSVassil Vassilev Expr *ArrSizeExpr = IntegerLiteralExpr(Ctx, ArrSize); 262*a72d7eeaSVassil Vassilev Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr}; 263*a72d7eeaSVassil Vassilev SetValueE = 264*a72d7eeaSVassil Vassilev S.ActOnCallExpr(Scope, ValuePrintingInfo[InterfaceKind::CopyArray], 265*a72d7eeaSVassil Vassilev SourceLocation(), Args, SourceLocation()); 266*a72d7eeaSVassil Vassilev } 267*a72d7eeaSVassil Vassilev Expr *Args[] = {AllocCall.get(), ValuePrintingInfo[InterfaceKind::NewTag]}; 268*a72d7eeaSVassil Vassilev ExprResult CXXNewCall = S.BuildCXXNew( 269*a72d7eeaSVassil Vassilev E->getSourceRange(), 270*a72d7eeaSVassil Vassilev /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args, 271*a72d7eeaSVassil Vassilev /*PlacementRParen=*/SourceLocation(), 272*a72d7eeaSVassil Vassilev /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt, 273*a72d7eeaSVassil Vassilev E->getSourceRange(), E); 274*a72d7eeaSVassil Vassilev 275*a72d7eeaSVassil Vassilev assert(!CXXNewCall.isInvalid() && 276*a72d7eeaSVassil Vassilev "Can't create runtime placement new call!"); 277*a72d7eeaSVassil Vassilev 278*a72d7eeaSVassil Vassilev SetValueE = S.ActOnFinishFullExpr(CXXNewCall.get(), 279*a72d7eeaSVassil Vassilev /*DiscardedValue=*/false); 280*a72d7eeaSVassil Vassilev break; 281*a72d7eeaSVassil Vassilev } 282*a72d7eeaSVassil Vassilev // __clang_Interpreter_SetValueNoAlloc. 283*a72d7eeaSVassil Vassilev case InterfaceKind::NoAlloc: { 284*a72d7eeaSVassil Vassilev SetValueE = 285*a72d7eeaSVassil Vassilev S.ActOnCallExpr(Scope, ValuePrintingInfo[InterfaceKind::NoAlloc], 286*a72d7eeaSVassil Vassilev E->getBeginLoc(), AdjustedArgs, E->getEndLoc()); 287*a72d7eeaSVassil Vassilev break; 288*a72d7eeaSVassil Vassilev } 289*a72d7eeaSVassil Vassilev default: 290*a72d7eeaSVassil Vassilev llvm_unreachable("Unhandled InterfaceKind"); 291*a72d7eeaSVassil Vassilev } 292*a72d7eeaSVassil Vassilev 293*a72d7eeaSVassil Vassilev // It could fail, like printing an array type in C. (not supported) 294*a72d7eeaSVassil Vassilev if (SetValueE.isInvalid()) 295*a72d7eeaSVassil Vassilev return E; 296*a72d7eeaSVassil Vassilev 297*a72d7eeaSVassil Vassilev return SetValueE.get(); 298*a72d7eeaSVassil Vassilev } 299*a72d7eeaSVassil Vassilev 300*a72d7eeaSVassil Vassilev } // namespace clang 301*a72d7eeaSVassil Vassilev 302*a72d7eeaSVassil Vassilev using namespace clang; 303*a72d7eeaSVassil Vassilev 304*a72d7eeaSVassil Vassilev // Temporary rvalue struct that need special care. 305*a72d7eeaSVassil Vassilev REPL_EXTERNAL_VISIBILITY void * 306*a72d7eeaSVassil Vassilev __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, 307*a72d7eeaSVassil Vassilev void *OpaqueType) { 308*a72d7eeaSVassil Vassilev Value &VRef = *(Value *)OutVal; 309*a72d7eeaSVassil Vassilev VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 310*a72d7eeaSVassil Vassilev return VRef.getPtr(); 311*a72d7eeaSVassil Vassilev } 312*a72d7eeaSVassil Vassilev 313*a72d7eeaSVassil Vassilev extern "C" void REPL_EXTERNAL_VISIBILITY __clang_Interpreter_SetValueNoAlloc( 314*a72d7eeaSVassil Vassilev void *This, void *OutVal, void *OpaqueType, ...) { 315*a72d7eeaSVassil Vassilev Value &VRef = *(Value *)OutVal; 316*a72d7eeaSVassil Vassilev Interpreter *I = static_cast<Interpreter *>(This); 317*a72d7eeaSVassil Vassilev VRef = Value(I, OpaqueType); 318*a72d7eeaSVassil Vassilev if (VRef.isVoid()) 319*a72d7eeaSVassil Vassilev return; 320*a72d7eeaSVassil Vassilev 321*a72d7eeaSVassil Vassilev va_list args; 322*a72d7eeaSVassil Vassilev va_start(args, /*last named param*/ OpaqueType); 323*a72d7eeaSVassil Vassilev 324*a72d7eeaSVassil Vassilev QualType QT = VRef.getType(); 325*a72d7eeaSVassil Vassilev if (VRef.getKind() == Value::K_PtrOrObj) { 326*a72d7eeaSVassil Vassilev VRef.setPtr(va_arg(args, void *)); 327*a72d7eeaSVassil Vassilev } else { 328*a72d7eeaSVassil Vassilev if (const auto *ET = QT->getAs<EnumType>()) 329*a72d7eeaSVassil Vassilev QT = ET->getDecl()->getIntegerType(); 330*a72d7eeaSVassil Vassilev switch (QT->castAs<BuiltinType>()->getKind()) { 331*a72d7eeaSVassil Vassilev default: 332*a72d7eeaSVassil Vassilev llvm_unreachable("unknown type kind!"); 333*a72d7eeaSVassil Vassilev break; 334*a72d7eeaSVassil Vassilev // Types shorter than int are resolved as int, else va_arg has UB. 335*a72d7eeaSVassil Vassilev case BuiltinType::Bool: 336*a72d7eeaSVassil Vassilev VRef.setBool(va_arg(args, int)); 337*a72d7eeaSVassil Vassilev break; 338*a72d7eeaSVassil Vassilev case BuiltinType::Char_S: 339*a72d7eeaSVassil Vassilev VRef.setChar_S(va_arg(args, int)); 340*a72d7eeaSVassil Vassilev break; 341*a72d7eeaSVassil Vassilev case BuiltinType::SChar: 342*a72d7eeaSVassil Vassilev VRef.setSChar(va_arg(args, int)); 343*a72d7eeaSVassil Vassilev break; 344*a72d7eeaSVassil Vassilev case BuiltinType::Char_U: 345*a72d7eeaSVassil Vassilev VRef.setChar_U(va_arg(args, unsigned)); 346*a72d7eeaSVassil Vassilev break; 347*a72d7eeaSVassil Vassilev case BuiltinType::UChar: 348*a72d7eeaSVassil Vassilev VRef.setUChar(va_arg(args, unsigned)); 349*a72d7eeaSVassil Vassilev break; 350*a72d7eeaSVassil Vassilev case BuiltinType::Short: 351*a72d7eeaSVassil Vassilev VRef.setShort(va_arg(args, int)); 352*a72d7eeaSVassil Vassilev break; 353*a72d7eeaSVassil Vassilev case BuiltinType::UShort: 354*a72d7eeaSVassil Vassilev VRef.setUShort(va_arg(args, unsigned)); 355*a72d7eeaSVassil Vassilev break; 356*a72d7eeaSVassil Vassilev case BuiltinType::Int: 357*a72d7eeaSVassil Vassilev VRef.setInt(va_arg(args, int)); 358*a72d7eeaSVassil Vassilev break; 359*a72d7eeaSVassil Vassilev case BuiltinType::UInt: 360*a72d7eeaSVassil Vassilev VRef.setUInt(va_arg(args, unsigned)); 361*a72d7eeaSVassil Vassilev break; 362*a72d7eeaSVassil Vassilev case BuiltinType::Long: 363*a72d7eeaSVassil Vassilev VRef.setLong(va_arg(args, long)); 364*a72d7eeaSVassil Vassilev break; 365*a72d7eeaSVassil Vassilev case BuiltinType::ULong: 366*a72d7eeaSVassil Vassilev VRef.setULong(va_arg(args, unsigned long)); 367*a72d7eeaSVassil Vassilev break; 368*a72d7eeaSVassil Vassilev case BuiltinType::LongLong: 369*a72d7eeaSVassil Vassilev VRef.setLongLong(va_arg(args, long long)); 370*a72d7eeaSVassil Vassilev break; 371*a72d7eeaSVassil Vassilev case BuiltinType::ULongLong: 372*a72d7eeaSVassil Vassilev VRef.setULongLong(va_arg(args, unsigned long long)); 373*a72d7eeaSVassil Vassilev break; 374*a72d7eeaSVassil Vassilev // Types shorter than double are resolved as double, else va_arg has UB. 375*a72d7eeaSVassil Vassilev case BuiltinType::Float: 376*a72d7eeaSVassil Vassilev VRef.setFloat(va_arg(args, double)); 377*a72d7eeaSVassil Vassilev break; 378*a72d7eeaSVassil Vassilev case BuiltinType::Double: 379*a72d7eeaSVassil Vassilev VRef.setDouble(va_arg(args, double)); 380*a72d7eeaSVassil Vassilev break; 381*a72d7eeaSVassil Vassilev case BuiltinType::LongDouble: 382*a72d7eeaSVassil Vassilev VRef.setLongDouble(va_arg(args, long double)); 383*a72d7eeaSVassil Vassilev break; 384*a72d7eeaSVassil Vassilev // See REPL_BUILTIN_TYPES. 385*a72d7eeaSVassil Vassilev } 386*a72d7eeaSVassil Vassilev } 387*a72d7eeaSVassil Vassilev va_end(args); 388*a72d7eeaSVassil Vassilev } 389*a72d7eeaSVassil Vassilev 390*a72d7eeaSVassil Vassilev // A trampoline to work around the fact that operator placement new cannot 391*a72d7eeaSVassil Vassilev // really be forward declared due to libc++ and libstdc++ declaration mismatch. 392*a72d7eeaSVassil Vassilev // FIXME: __clang_Interpreter_NewTag is ODR violation because we get the same 393*a72d7eeaSVassil Vassilev // definition in the interpreter runtime. We should move it in a runtime header 394*a72d7eeaSVassil Vassilev // which gets included by the interpreter and here. 395*a72d7eeaSVassil Vassilev struct __clang_Interpreter_NewTag {}; 396*a72d7eeaSVassil Vassilev REPL_EXTERNAL_VISIBILITY void * 397*a72d7eeaSVassil Vassilev operator new(size_t __sz, void *__p, __clang_Interpreter_NewTag) noexcept { 398*a72d7eeaSVassil Vassilev // Just forward to the standard operator placement new. 399*a72d7eeaSVassil Vassilev return operator new(__sz, __p); 400*a72d7eeaSVassil Vassilev } 401