xref: /llvm-project/clang/lib/Interpreter/InterpreterValuePrinter.cpp (revision a72d7eea5413444249670579fecea6823fb3c564)
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