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