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