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