1 //===------ Interpreter.cpp - Incremental Compilation and Execution -------===// 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 the component which performs incremental code 10 // compilation and execution. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Interpreter/Interpreter.h" 15 16 #include "DeviceOffload.h" 17 #include "IncrementalExecutor.h" 18 #include "IncrementalParser.h" 19 20 #include "InterpreterUtils.h" 21 #include "clang/AST/ASTContext.h" 22 #include "clang/AST/Mangle.h" 23 #include "clang/AST/TypeVisitor.h" 24 #include "clang/Basic/DiagnosticSema.h" 25 #include "clang/Basic/TargetInfo.h" 26 #include "clang/CodeGen/CodeGenAction.h" 27 #include "clang/CodeGen/ModuleBuilder.h" 28 #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" 29 #include "clang/Driver/Compilation.h" 30 #include "clang/Driver/Driver.h" 31 #include "clang/Driver/Job.h" 32 #include "clang/Driver/Options.h" 33 #include "clang/Driver/Tool.h" 34 #include "clang/Frontend/CompilerInstance.h" 35 #include "clang/Frontend/TextDiagnosticBuffer.h" 36 #include "clang/Interpreter/Value.h" 37 #include "clang/Lex/PreprocessorOptions.h" 38 #include "clang/Sema/Lookup.h" 39 #include "llvm/ExecutionEngine/JITSymbol.h" 40 #include "llvm/ExecutionEngine/Orc/LLJIT.h" 41 #include "llvm/IR/Module.h" 42 #include "llvm/Support/Errc.h" 43 #include "llvm/Support/ErrorHandling.h" 44 #include "llvm/Support/raw_ostream.h" 45 #include "llvm/TargetParser/Host.h" 46 using namespace clang; 47 48 // FIXME: Figure out how to unify with namespace init_convenience from 49 // tools/clang-import-test/clang-import-test.cpp 50 namespace { 51 /// Retrieves the clang CC1 specific flags out of the compilation's jobs. 52 /// \returns NULL on error. 53 static llvm::Expected<const llvm::opt::ArgStringList *> 54 GetCC1Arguments(DiagnosticsEngine *Diagnostics, 55 driver::Compilation *Compilation) { 56 // We expect to get back exactly one Command job, if we didn't something 57 // failed. Extract that job from the Compilation. 58 const driver::JobList &Jobs = Compilation->getJobs(); 59 if (!Jobs.size() || !isa<driver::Command>(*Jobs.begin())) 60 return llvm::createStringError(llvm::errc::not_supported, 61 "Driver initialization failed. " 62 "Unable to create a driver job"); 63 64 // The one job we find should be to invoke clang again. 65 const driver::Command *Cmd = cast<driver::Command>(&(*Jobs.begin())); 66 if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") 67 return llvm::createStringError(llvm::errc::not_supported, 68 "Driver initialization failed"); 69 70 return &Cmd->getArguments(); 71 } 72 73 static llvm::Expected<std::unique_ptr<CompilerInstance>> 74 CreateCI(const llvm::opt::ArgStringList &Argv) { 75 std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); 76 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 77 78 // Register the support for object-file-wrapped Clang modules. 79 // FIXME: Clang should register these container operations automatically. 80 auto PCHOps = Clang->getPCHContainerOperations(); 81 PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>()); 82 PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>()); 83 84 // Buffer diagnostics from argument parsing so that we can output them using 85 // a well formed diagnostic object. 86 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 87 TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; 88 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); 89 bool Success = CompilerInvocation::CreateFromArgs( 90 Clang->getInvocation(), llvm::ArrayRef(Argv.begin(), Argv.size()), Diags); 91 92 // Infer the builtin include path if unspecified. 93 if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && 94 Clang->getHeaderSearchOpts().ResourceDir.empty()) 95 Clang->getHeaderSearchOpts().ResourceDir = 96 CompilerInvocation::GetResourcesPath(Argv[0], nullptr); 97 98 // Create the actual diagnostics engine. 99 Clang->createDiagnostics(); 100 if (!Clang->hasDiagnostics()) 101 return llvm::createStringError(llvm::errc::not_supported, 102 "Initialization failed. " 103 "Unable to create diagnostics engine"); 104 105 DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics()); 106 if (!Success) 107 return llvm::createStringError(llvm::errc::not_supported, 108 "Initialization failed. " 109 "Unable to flush diagnostics"); 110 111 // FIXME: Merge with CompilerInstance::ExecuteAction. 112 llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer("").release(); 113 Clang->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB); 114 115 Clang->setTarget(TargetInfo::CreateTargetInfo( 116 Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); 117 if (!Clang->hasTarget()) 118 return llvm::createStringError(llvm::errc::not_supported, 119 "Initialization failed. " 120 "Target is missing"); 121 122 Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts()); 123 124 // Don't clear the AST before backend codegen since we do codegen multiple 125 // times, reusing the same AST. 126 Clang->getCodeGenOpts().ClearASTBeforeBackend = false; 127 128 Clang->getFrontendOpts().DisableFree = false; 129 Clang->getCodeGenOpts().DisableFree = false; 130 131 return std::move(Clang); 132 } 133 134 } // anonymous namespace 135 136 llvm::Expected<std::unique_ptr<CompilerInstance>> 137 IncrementalCompilerBuilder::create(std::vector<const char *> &ClangArgv) { 138 139 // If we don't know ClangArgv0 or the address of main() at this point, try 140 // to guess it anyway (it's possible on some platforms). 141 std::string MainExecutableName = 142 llvm::sys::fs::getMainExecutable(nullptr, nullptr); 143 144 ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str()); 145 146 // Prepending -c to force the driver to do something if no action was 147 // specified. By prepending we allow users to override the default 148 // action and use other actions in incremental mode. 149 // FIXME: Print proper driver diagnostics if the driver flags are wrong. 150 // We do C++ by default; append right after argv[0] if no "-x" given 151 ClangArgv.insert(ClangArgv.end(), "-Xclang"); 152 ClangArgv.insert(ClangArgv.end(), "-fincremental-extensions"); 153 ClangArgv.insert(ClangArgv.end(), "-c"); 154 155 // Put a dummy C++ file on to ensure there's at least one compile job for the 156 // driver to construct. 157 ClangArgv.push_back("<<< inputs >>>"); 158 159 // Buffer diagnostics from argument parsing so that we can output them using a 160 // well formed diagnostic object. 161 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 162 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = 163 CreateAndPopulateDiagOpts(ClangArgv); 164 TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; 165 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); 166 167 driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], 168 llvm::sys::getProcessTriple(), Diags); 169 Driver.setCheckInputsExist(false); // the input comes from mem buffers 170 llvm::ArrayRef<const char *> RF = llvm::ArrayRef(ClangArgv); 171 std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF)); 172 173 if (Compilation->getArgs().hasArg(driver::options::OPT_v)) 174 Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false); 175 176 auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get()); 177 if (auto Err = ErrOrCC1Args.takeError()) 178 return std::move(Err); 179 180 return CreateCI(**ErrOrCC1Args); 181 } 182 183 llvm::Expected<std::unique_ptr<CompilerInstance>> 184 IncrementalCompilerBuilder::CreateCpp() { 185 std::vector<const char *> Argv; 186 Argv.reserve(5 + 1 + UserArgs.size()); 187 Argv.push_back("-xc++"); 188 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end()); 189 190 return IncrementalCompilerBuilder::create(Argv); 191 } 192 193 llvm::Expected<std::unique_ptr<CompilerInstance>> 194 IncrementalCompilerBuilder::createCuda(bool device) { 195 std::vector<const char *> Argv; 196 Argv.reserve(5 + 4 + UserArgs.size()); 197 198 Argv.push_back("-xcuda"); 199 if (device) 200 Argv.push_back("--cuda-device-only"); 201 else 202 Argv.push_back("--cuda-host-only"); 203 204 std::string SDKPathArg = "--cuda-path="; 205 if (!CudaSDKPath.empty()) { 206 SDKPathArg += CudaSDKPath; 207 Argv.push_back(SDKPathArg.c_str()); 208 } 209 210 std::string ArchArg = "--offload-arch="; 211 if (!OffloadArch.empty()) { 212 ArchArg += OffloadArch; 213 Argv.push_back(ArchArg.c_str()); 214 } 215 216 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end()); 217 218 return IncrementalCompilerBuilder::create(Argv); 219 } 220 221 llvm::Expected<std::unique_ptr<CompilerInstance>> 222 IncrementalCompilerBuilder::CreateCudaDevice() { 223 return IncrementalCompilerBuilder::createCuda(true); 224 } 225 226 llvm::Expected<std::unique_ptr<CompilerInstance>> 227 IncrementalCompilerBuilder::CreateCudaHost() { 228 return IncrementalCompilerBuilder::createCuda(false); 229 } 230 231 Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI, 232 llvm::Error &Err) { 233 llvm::ErrorAsOutParameter EAO(&Err); 234 auto LLVMCtx = std::make_unique<llvm::LLVMContext>(); 235 TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx)); 236 IncrParser = std::make_unique<IncrementalParser>(*this, std::move(CI), 237 *TSCtx->getContext(), Err); 238 } 239 240 Interpreter::~Interpreter() { 241 if (IncrExecutor) { 242 if (llvm::Error Err = IncrExecutor->cleanUp()) 243 llvm::report_fatal_error( 244 llvm::Twine("Failed to clean up IncrementalExecutor: ") + 245 toString(std::move(Err))); 246 } 247 } 248 249 // These better to put in a runtime header but we can't. This is because we 250 // can't find the precise resource directory in unittests so we have to hard 251 // code them. 252 const char *const Runtimes = R"( 253 void* operator new(__SIZE_TYPE__, void* __p) noexcept; 254 void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*); 255 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*); 256 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*); 257 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float); 258 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double); 259 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double); 260 void __clang_Interpreter_SetValueNoAlloc(void*,void*,void*,unsigned long long); 261 template <class T, class = T (*)() /*disable for arrays*/> 262 void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) { 263 for (auto Idx = 0; Idx < Size; ++Idx) 264 new ((void*)(((T*)Placement) + Idx)) T(Src[Idx]); 265 } 266 template <class T, unsigned long N> 267 void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) { 268 __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size); 269 } 270 )"; 271 272 llvm::Expected<std::unique_ptr<Interpreter>> 273 Interpreter::create(std::unique_ptr<CompilerInstance> CI) { 274 llvm::Error Err = llvm::Error::success(); 275 auto Interp = 276 std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err)); 277 if (Err) 278 return std::move(Err); 279 auto PTU = Interp->Parse(Runtimes); 280 if (!PTU) 281 return PTU.takeError(); 282 283 Interp->ValuePrintingInfo.resize(3); 284 // FIXME: This is a ugly hack. Undo command checks its availability by looking 285 // at the size of the PTU list. However we have parsed something in the 286 // beginning of the REPL so we have to mark them as 'Irrevocable'. 287 Interp->InitPTUSize = Interp->IncrParser->getPTUs().size(); 288 return std::move(Interp); 289 } 290 291 llvm::Expected<std::unique_ptr<Interpreter>> 292 Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI, 293 std::unique_ptr<CompilerInstance> DCI) { 294 // avoid writing fat binary to disk using an in-memory virtual file system 295 llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> IMVFS = 296 std::make_unique<llvm::vfs::InMemoryFileSystem>(); 297 llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS = 298 std::make_unique<llvm::vfs::OverlayFileSystem>( 299 llvm::vfs::getRealFileSystem()); 300 OverlayVFS->pushOverlay(IMVFS); 301 CI->createFileManager(OverlayVFS); 302 303 auto Interp = Interpreter::create(std::move(CI)); 304 if (auto E = Interp.takeError()) 305 return std::move(E); 306 307 llvm::Error Err = llvm::Error::success(); 308 auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>( 309 **Interp, std::move(DCI), *(*Interp)->IncrParser.get(), 310 *(*Interp)->TSCtx->getContext(), IMVFS, Err); 311 if (Err) 312 return std::move(Err); 313 314 (*Interp)->DeviceParser = std::move(DeviceParser); 315 316 return Interp; 317 } 318 319 const CompilerInstance *Interpreter::getCompilerInstance() const { 320 return IncrParser->getCI(); 321 } 322 323 llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() { 324 if (!IncrExecutor) { 325 if (auto Err = CreateExecutor()) 326 return std::move(Err); 327 } 328 329 return IncrExecutor->GetExecutionEngine(); 330 } 331 332 ASTContext &Interpreter::getASTContext() { 333 return getCompilerInstance()->getASTContext(); 334 } 335 336 const ASTContext &Interpreter::getASTContext() const { 337 return getCompilerInstance()->getASTContext(); 338 } 339 340 size_t Interpreter::getEffectivePTUSize() const { 341 std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs(); 342 assert(PTUs.size() >= InitPTUSize && "empty PTU list?"); 343 return PTUs.size() - InitPTUSize; 344 } 345 346 llvm::Expected<PartialTranslationUnit &> 347 Interpreter::Parse(llvm::StringRef Code) { 348 // If we have a device parser, parse it first. 349 // The generated code will be included in the host compilation 350 if (DeviceParser) { 351 auto DevicePTU = DeviceParser->Parse(Code); 352 if (auto E = DevicePTU.takeError()) 353 return std::move(E); 354 } 355 356 // Tell the interpreter sliently ignore unused expressions since value 357 // printing could cause it. 358 getCompilerInstance()->getDiagnostics().setSeverity( 359 clang::diag::warn_unused_expr, diag::Severity::Ignored, SourceLocation()); 360 return IncrParser->Parse(Code); 361 } 362 363 llvm::Error Interpreter::CreateExecutor() { 364 const clang::TargetInfo &TI = 365 getCompilerInstance()->getASTContext().getTargetInfo(); 366 llvm::Error Err = llvm::Error::success(); 367 auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, Err, TI); 368 if (!Err) 369 IncrExecutor = std::move(Executor); 370 371 return Err; 372 } 373 374 llvm::Error Interpreter::Execute(PartialTranslationUnit &T) { 375 assert(T.TheModule); 376 if (!IncrExecutor) { 377 auto Err = CreateExecutor(); 378 if (Err) 379 return Err; 380 } 381 // FIXME: Add a callback to retain the llvm::Module once the JIT is done. 382 if (auto Err = IncrExecutor->addModule(T)) 383 return Err; 384 385 if (auto Err = IncrExecutor->runCtors()) 386 return Err; 387 388 return llvm::Error::success(); 389 } 390 391 llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) { 392 393 auto PTU = Parse(Code); 394 if (!PTU) 395 return PTU.takeError(); 396 if (PTU->TheModule) 397 if (llvm::Error Err = Execute(*PTU)) 398 return Err; 399 400 if (LastValue.isValid()) { 401 if (!V) { 402 LastValue.dump(); 403 LastValue.clear(); 404 } else 405 *V = std::move(LastValue); 406 } 407 return llvm::Error::success(); 408 } 409 410 llvm::Expected<llvm::orc::ExecutorAddr> 411 Interpreter::getSymbolAddress(GlobalDecl GD) const { 412 if (!IncrExecutor) 413 return llvm::make_error<llvm::StringError>("Operation failed. " 414 "No execution engine", 415 std::error_code()); 416 llvm::StringRef MangledName = IncrParser->GetMangledName(GD); 417 return getSymbolAddress(MangledName); 418 } 419 420 llvm::Expected<llvm::orc::ExecutorAddr> 421 Interpreter::getSymbolAddress(llvm::StringRef IRName) const { 422 if (!IncrExecutor) 423 return llvm::make_error<llvm::StringError>("Operation failed. " 424 "No execution engine", 425 std::error_code()); 426 427 return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName); 428 } 429 430 llvm::Expected<llvm::orc::ExecutorAddr> 431 Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const { 432 if (!IncrExecutor) 433 return llvm::make_error<llvm::StringError>("Operation failed. " 434 "No execution engine", 435 std::error_code()); 436 437 return IncrExecutor->getSymbolAddress(Name, IncrementalExecutor::LinkerName); 438 } 439 440 llvm::Error Interpreter::Undo(unsigned N) { 441 442 std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs(); 443 if (N > getEffectivePTUSize()) 444 return llvm::make_error<llvm::StringError>("Operation failed. " 445 "Too many undos", 446 std::error_code()); 447 for (unsigned I = 0; I < N; I++) { 448 if (IncrExecutor) { 449 if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back())) 450 return Err; 451 } 452 453 IncrParser->CleanUpPTU(PTUs.back()); 454 PTUs.pop_back(); 455 } 456 return llvm::Error::success(); 457 } 458 459 llvm::Error Interpreter::LoadDynamicLibrary(const char *name) { 460 auto EE = getExecutionEngine(); 461 if (!EE) 462 return EE.takeError(); 463 464 auto &DL = EE->getDataLayout(); 465 466 if (auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load( 467 name, DL.getGlobalPrefix())) 468 EE->getMainJITDylib().addGenerator(std::move(*DLSG)); 469 else 470 return DLSG.takeError(); 471 472 return llvm::Error::success(); 473 } 474 475 llvm::Expected<llvm::orc::ExecutorAddr> 476 Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) { 477 assert(CXXRD && "Cannot compile a destructor for a nullptr"); 478 if (auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end()) 479 return Dtor->getSecond(); 480 481 if (CXXRD->hasIrrelevantDestructor()) 482 return llvm::orc::ExecutorAddr{}; 483 484 CXXDestructorDecl *DtorRD = 485 getCompilerInstance()->getSema().LookupDestructor(CXXRD); 486 487 llvm::StringRef Name = 488 IncrParser->GetMangledName(GlobalDecl(DtorRD, Dtor_Base)); 489 auto AddrOrErr = getSymbolAddress(Name); 490 if (!AddrOrErr) 491 return AddrOrErr.takeError(); 492 493 Dtors[CXXRD] = *AddrOrErr; 494 return AddrOrErr; 495 } 496 497 static constexpr llvm::StringRef MagicRuntimeInterface[] = { 498 "__clang_Interpreter_SetValueNoAlloc", 499 "__clang_Interpreter_SetValueWithAlloc", 500 "__clang_Interpreter_SetValueCopyArr"}; 501 502 bool Interpreter::FindRuntimeInterface() { 503 if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; })) 504 return true; 505 506 Sema &S = getCompilerInstance()->getSema(); 507 ASTContext &Ctx = S.getASTContext(); 508 509 auto LookupInterface = [&](Expr *&Interface, llvm::StringRef Name) { 510 LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(), 511 Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration); 512 S.LookupQualifiedName(R, Ctx.getTranslationUnitDecl()); 513 if (R.empty()) 514 return false; 515 516 CXXScopeSpec CSS; 517 Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get(); 518 return true; 519 }; 520 521 if (!LookupInterface(ValuePrintingInfo[NoAlloc], 522 MagicRuntimeInterface[NoAlloc])) 523 return false; 524 if (!LookupInterface(ValuePrintingInfo[WithAlloc], 525 MagicRuntimeInterface[WithAlloc])) 526 return false; 527 if (!LookupInterface(ValuePrintingInfo[CopyArray], 528 MagicRuntimeInterface[CopyArray])) 529 return false; 530 return true; 531 } 532 533 namespace { 534 535 class RuntimeInterfaceBuilder 536 : public TypeVisitor<RuntimeInterfaceBuilder, Interpreter::InterfaceKind> { 537 clang::Interpreter &Interp; 538 ASTContext &Ctx; 539 Sema &S; 540 Expr *E; 541 llvm::SmallVector<Expr *, 3> Args; 542 543 public: 544 RuntimeInterfaceBuilder(clang::Interpreter &In, ASTContext &C, Sema &SemaRef, 545 Expr *VE, ArrayRef<Expr *> FixedArgs) 546 : Interp(In), Ctx(C), S(SemaRef), E(VE) { 547 // The Interpreter* parameter and the out parameter `OutVal`. 548 for (Expr *E : FixedArgs) 549 Args.push_back(E); 550 551 // Get rid of ExprWithCleanups. 552 if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E)) 553 E = EWC->getSubExpr(); 554 } 555 556 ExprResult getCall() { 557 QualType Ty = E->getType(); 558 QualType DesugaredTy = Ty.getDesugaredType(Ctx); 559 560 // For lvalue struct, we treat it as a reference. 561 if (DesugaredTy->isRecordType() && E->isLValue()) { 562 DesugaredTy = Ctx.getLValueReferenceType(DesugaredTy); 563 Ty = Ctx.getLValueReferenceType(Ty); 564 } 565 566 Expr *TypeArg = 567 CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)Ty.getAsOpaquePtr()); 568 // The QualType parameter `OpaqueType`, represented as `void*`. 569 Args.push_back(TypeArg); 570 571 // We push the last parameter based on the type of the Expr. Note we need 572 // special care for rvalue struct. 573 Interpreter::InterfaceKind Kind = Visit(&*DesugaredTy); 574 switch (Kind) { 575 case Interpreter::InterfaceKind::WithAlloc: 576 case Interpreter::InterfaceKind::CopyArray: { 577 // __clang_Interpreter_SetValueWithAlloc. 578 ExprResult AllocCall = S.ActOnCallExpr( 579 /*Scope=*/nullptr, 580 Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc], 581 E->getBeginLoc(), Args, E->getEndLoc()); 582 assert(!AllocCall.isInvalid() && "Can't create runtime interface call!"); 583 584 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation()); 585 586 // Force CodeGen to emit destructor. 587 if (auto *RD = Ty->getAsCXXRecordDecl()) { 588 auto *Dtor = S.LookupDestructor(RD); 589 Dtor->addAttr(UsedAttr::CreateImplicit(Ctx)); 590 Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl( 591 DeclGroupRef(Dtor)); 592 } 593 594 // __clang_Interpreter_SetValueCopyArr. 595 if (Kind == Interpreter::InterfaceKind::CopyArray) { 596 const auto *ConstantArrTy = 597 cast<ConstantArrayType>(DesugaredTy.getTypePtr()); 598 size_t ArrSize = Ctx.getConstantArrayElementCount(ConstantArrTy); 599 Expr *ArrSizeExpr = IntegerLiteralExpr(Ctx, ArrSize); 600 Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr}; 601 return S.ActOnCallExpr( 602 /*Scope *=*/nullptr, 603 Interp 604 .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray], 605 SourceLocation(), Args, SourceLocation()); 606 } 607 Expr *Args[] = {AllocCall.get()}; 608 ExprResult CXXNewCall = S.BuildCXXNew( 609 E->getSourceRange(), 610 /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args, 611 /*PlacementRParen=*/SourceLocation(), 612 /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt, 613 E->getSourceRange(), E); 614 615 assert(!CXXNewCall.isInvalid() && 616 "Can't create runtime placement new call!"); 617 618 return S.ActOnFinishFullExpr(CXXNewCall.get(), 619 /*DiscardedValue=*/false); 620 } 621 // __clang_Interpreter_SetValueNoAlloc. 622 case Interpreter::InterfaceKind::NoAlloc: { 623 return S.ActOnCallExpr( 624 /*Scope=*/nullptr, 625 Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc], 626 E->getBeginLoc(), Args, E->getEndLoc()); 627 } 628 } 629 llvm_unreachable("Unhandled Interpreter::InterfaceKind"); 630 } 631 632 Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) { 633 return Interpreter::InterfaceKind::WithAlloc; 634 } 635 636 Interpreter::InterfaceKind 637 VisitMemberPointerType(const MemberPointerType *Ty) { 638 return Interpreter::InterfaceKind::WithAlloc; 639 } 640 641 Interpreter::InterfaceKind 642 VisitConstantArrayType(const ConstantArrayType *Ty) { 643 return Interpreter::InterfaceKind::CopyArray; 644 } 645 646 Interpreter::InterfaceKind 647 VisitFunctionProtoType(const FunctionProtoType *Ty) { 648 HandlePtrType(Ty); 649 return Interpreter::InterfaceKind::NoAlloc; 650 } 651 652 Interpreter::InterfaceKind VisitPointerType(const PointerType *Ty) { 653 HandlePtrType(Ty); 654 return Interpreter::InterfaceKind::NoAlloc; 655 } 656 657 Interpreter::InterfaceKind VisitReferenceType(const ReferenceType *Ty) { 658 ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, E); 659 assert(!AddrOfE.isInvalid() && "Can not create unary expression"); 660 Args.push_back(AddrOfE.get()); 661 return Interpreter::InterfaceKind::NoAlloc; 662 } 663 664 Interpreter::InterfaceKind VisitBuiltinType(const BuiltinType *Ty) { 665 if (Ty->isNullPtrType()) 666 Args.push_back(E); 667 else if (Ty->isFloatingType()) 668 Args.push_back(E); 669 else if (Ty->isIntegralOrEnumerationType()) 670 HandleIntegralOrEnumType(Ty); 671 else if (Ty->isVoidType()) { 672 // Do we need to still run `E`? 673 } 674 675 return Interpreter::InterfaceKind::NoAlloc; 676 } 677 678 Interpreter::InterfaceKind VisitEnumType(const EnumType *Ty) { 679 HandleIntegralOrEnumType(Ty); 680 return Interpreter::InterfaceKind::NoAlloc; 681 } 682 683 private: 684 // Force cast these types to uint64 to reduce the number of overloads of 685 // `__clang_Interpreter_SetValueNoAlloc`. 686 void HandleIntegralOrEnumType(const Type *Ty) { 687 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ctx.UnsignedLongLongTy); 688 ExprResult CastedExpr = 689 S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E); 690 assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr"); 691 Args.push_back(CastedExpr.get()); 692 } 693 694 void HandlePtrType(const Type *Ty) { 695 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ctx.VoidPtrTy); 696 ExprResult CastedExpr = 697 S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E); 698 assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression"); 699 Args.push_back(CastedExpr.get()); 700 } 701 }; 702 } // namespace 703 704 // This synthesizes a call expression to a speciall 705 // function that is responsible for generating the Value. 706 // In general, we transform: 707 // clang-repl> x 708 // To: 709 // // 1. If x is a built-in type like int, float. 710 // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x); 711 // // 2. If x is a struct, and a lvalue. 712 // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, 713 // &x); 714 // // 3. If x is a struct, but a rvalue. 715 // new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue, 716 // xQualType)) (x); 717 718 Expr *Interpreter::SynthesizeExpr(Expr *E) { 719 Sema &S = getCompilerInstance()->getSema(); 720 ASTContext &Ctx = S.getASTContext(); 721 722 if (!FindRuntimeInterface()) 723 llvm_unreachable("We can't find the runtime iterface for pretty print!"); 724 725 // Create parameter `ThisInterp`. 726 auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this); 727 728 // Create parameter `OutVal`. 729 auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue); 730 731 // Build `__clang_Interpreter_SetValue*` call. 732 RuntimeInterfaceBuilder Builder(*this, Ctx, S, E, {ThisInterp, OutValue}); 733 734 ExprResult Result = Builder.getCall(); 735 // It could fail, like printing an array type in C. (not supported) 736 if (Result.isInvalid()) 737 return E; 738 return Result.get(); 739 } 740 741 // Temporary rvalue struct that need special care. 742 REPL_EXTERNAL_VISIBILITY void * 743 __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, 744 void *OpaqueType) { 745 Value &VRef = *(Value *)OutVal; 746 VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 747 return VRef.getPtr(); 748 } 749 750 // Pointers, lvalue struct that can take as a reference. 751 REPL_EXTERNAL_VISIBILITY void 752 __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, 753 void *Val) { 754 Value &VRef = *(Value *)OutVal; 755 VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 756 VRef.setPtr(Val); 757 } 758 759 REPL_EXTERNAL_VISIBILITY void 760 __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, 761 void *OpaqueType) { 762 Value &VRef = *(Value *)OutVal; 763 VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 764 } 765 766 static void SetValueDataBasedOnQualType(Value &V, unsigned long long Data) { 767 QualType QT = V.getType(); 768 if (const auto *ET = QT->getAs<EnumType>()) 769 QT = ET->getDecl()->getIntegerType(); 770 771 switch (QT->castAs<BuiltinType>()->getKind()) { 772 default: 773 llvm_unreachable("unknown type kind!"); 774 #define X(type, name) \ 775 case BuiltinType::name: \ 776 V.set##name(Data); \ 777 break; 778 REPL_BUILTIN_TYPES 779 #undef X 780 } 781 } 782 783 REPL_EXTERNAL_VISIBILITY void 784 __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, 785 unsigned long long Val) { 786 Value &VRef = *(Value *)OutVal; 787 VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 788 SetValueDataBasedOnQualType(VRef, Val); 789 } 790 791 REPL_EXTERNAL_VISIBILITY void 792 __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, 793 float Val) { 794 Value &VRef = *(Value *)OutVal; 795 VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 796 VRef.setFloat(Val); 797 } 798 799 REPL_EXTERNAL_VISIBILITY void 800 __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, 801 double Val) { 802 Value &VRef = *(Value *)OutVal; 803 VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 804 VRef.setDouble(Val); 805 } 806 807 REPL_EXTERNAL_VISIBILITY void 808 __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, 809 long double Val) { 810 Value &VRef = *(Value *)OutVal; 811 VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 812 VRef.setLongDouble(Val); 813 } 814