clang  20.0.0git
Interpreter.cpp
Go to the documentation of this file.
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 "DeviceOffload.h"
15 #include "IncrementalExecutor.h"
16 #include "IncrementalParser.h"
17 #include "InterpreterUtils.h"
18 #ifdef __EMSCRIPTEN__
19 #include "Wasm.h"
20 #endif // __EMSCRIPTEN__
21 
22 #include "clang/AST/ASTContext.h"
23 #include "clang/AST/Mangle.h"
24 #include "clang/AST/TypeVisitor.h"
26 #include "clang/Basic/TargetInfo.h"
31 #include "clang/Driver/Driver.h"
32 #include "clang/Driver/Job.h"
33 #include "clang/Driver/Options.h"
34 #include "clang/Driver/Tool.h"
40 #include "clang/Sema/Lookup.h"
42 #include "llvm/ExecutionEngine/JITSymbol.h"
43 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
44 #include "llvm/IR/Module.h"
45 #include "llvm/Support/Errc.h"
46 #include "llvm/Support/ErrorHandling.h"
47 #include "llvm/Support/raw_ostream.h"
48 #include "llvm/TargetParser/Host.h"
49 
50 #include <cstdarg>
51 
52 using namespace clang;
53 
54 // FIXME: Figure out how to unify with namespace init_convenience from
55 // tools/clang-import-test/clang-import-test.cpp
56 namespace {
57 /// Retrieves the clang CC1 specific flags out of the compilation's jobs.
58 /// \returns NULL on error.
60 GetCC1Arguments(DiagnosticsEngine *Diagnostics,
61  driver::Compilation *Compilation) {
62  // We expect to get back exactly one Command job, if we didn't something
63  // failed. Extract that job from the Compilation.
64  const driver::JobList &Jobs = Compilation->getJobs();
65  if (!Jobs.size() || !isa<driver::Command>(*Jobs.begin()))
66  return llvm::createStringError(llvm::errc::not_supported,
67  "Driver initialization failed. "
68  "Unable to create a driver job");
69 
70  // The one job we find should be to invoke clang again.
71  const driver::Command *Cmd = cast<driver::Command>(&(*Jobs.begin()));
72  if (llvm::StringRef(Cmd->getCreator().getName()) != "clang")
73  return llvm::createStringError(llvm::errc::not_supported,
74  "Driver initialization failed");
75 
76  return &Cmd->getArguments();
77 }
78 
80 CreateCI(const llvm::opt::ArgStringList &Argv) {
81  std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
83 
84  // Register the support for object-file-wrapped Clang modules.
85  // FIXME: Clang should register these container operations automatically.
86  auto PCHOps = Clang->getPCHContainerOperations();
87  PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
88  PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());
89 
90  // Buffer diagnostics from argument parsing so that we can output them using
91  // a well formed diagnostic object.
93  TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
94  DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
96  Clang->getInvocation(), llvm::ArrayRef(Argv.begin(), Argv.size()), Diags);
97 
98  // Infer the builtin include path if unspecified.
99  if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
100  Clang->getHeaderSearchOpts().ResourceDir.empty())
101  Clang->getHeaderSearchOpts().ResourceDir =
102  CompilerInvocation::GetResourcesPath(Argv[0], nullptr);
103 
104  // Create the actual diagnostics engine.
105  Clang->createDiagnostics();
106  if (!Clang->hasDiagnostics())
107  return llvm::createStringError(llvm::errc::not_supported,
108  "Initialization failed. "
109  "Unable to create diagnostics engine");
110 
111  DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
112  if (!Success)
113  return llvm::createStringError(llvm::errc::not_supported,
114  "Initialization failed. "
115  "Unable to flush diagnostics");
116 
117  // FIXME: Merge with CompilerInstance::ExecuteAction.
118  llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer("").release();
119  Clang->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB);
120 
121  Clang->setTarget(TargetInfo::CreateTargetInfo(
122  Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
123  if (!Clang->hasTarget())
124  return llvm::createStringError(llvm::errc::not_supported,
125  "Initialization failed. "
126  "Target is missing");
127 
128  Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts());
129 
130  // Don't clear the AST before backend codegen since we do codegen multiple
131  // times, reusing the same AST.
132  Clang->getCodeGenOpts().ClearASTBeforeBackend = false;
133 
134  Clang->getFrontendOpts().DisableFree = false;
135  Clang->getCodeGenOpts().DisableFree = false;
136  return std::move(Clang);
137 }
138 
139 } // anonymous namespace
140 
142 IncrementalCompilerBuilder::create(std::string TT,
143  std::vector<const char *> &ClangArgv) {
144 
145  // If we don't know ClangArgv0 or the address of main() at this point, try
146  // to guess it anyway (it's possible on some platforms).
147  std::string MainExecutableName =
148  llvm::sys::fs::getMainExecutable(nullptr, nullptr);
149 
150  ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str());
151 
152  // Prepending -c to force the driver to do something if no action was
153  // specified. By prepending we allow users to override the default
154  // action and use other actions in incremental mode.
155  // FIXME: Print proper driver diagnostics if the driver flags are wrong.
156  // We do C++ by default; append right after argv[0] if no "-x" given
157  ClangArgv.insert(ClangArgv.end(), "-Xclang");
158  ClangArgv.insert(ClangArgv.end(), "-fincremental-extensions");
159  ClangArgv.insert(ClangArgv.end(), "-c");
160 
161  // Put a dummy C++ file on to ensure there's at least one compile job for the
162  // driver to construct.
163  ClangArgv.push_back("<<< inputs >>>");
164 
165  // Buffer diagnostics from argument parsing so that we can output them using a
166  // well formed diagnostic object.
169  CreateAndPopulateDiagOpts(ClangArgv);
170  TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
171  DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
172 
173  driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], TT, Diags);
174  Driver.setCheckInputsExist(false); // the input comes from mem buffers
176  std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF));
177 
178  if (Compilation->getArgs().hasArg(driver::options::OPT_v))
179  Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false);
180 
181  auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get());
182  if (auto Err = ErrOrCC1Args.takeError())
183  return std::move(Err);
184 
185  return CreateCI(**ErrOrCC1Args);
186 }
187 
190  std::vector<const char *> Argv;
191  Argv.reserve(5 + 1 + UserArgs.size());
192  Argv.push_back("-xc++");
193 #ifdef __EMSCRIPTEN__
194  Argv.push_back("-target");
195  Argv.push_back("wasm32-unknown-emscripten");
196  Argv.push_back("-pie");
197  Argv.push_back("-shared");
198 #endif
199  Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
200 
201  std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
202  return IncrementalCompilerBuilder::create(TT, Argv);
203 }
204 
206 IncrementalCompilerBuilder::createCuda(bool device) {
207  std::vector<const char *> Argv;
208  Argv.reserve(5 + 4 + UserArgs.size());
209 
210  Argv.push_back("-xcuda");
211  if (device)
212  Argv.push_back("--cuda-device-only");
213  else
214  Argv.push_back("--cuda-host-only");
215 
216  std::string SDKPathArg = "--cuda-path=";
217  if (!CudaSDKPath.empty()) {
218  SDKPathArg += CudaSDKPath;
219  Argv.push_back(SDKPathArg.c_str());
220  }
221 
222  std::string ArchArg = "--offload-arch=";
223  if (!OffloadArch.empty()) {
224  ArchArg += OffloadArch;
225  Argv.push_back(ArchArg.c_str());
226  }
227 
228  Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
229 
230  std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
231  return IncrementalCompilerBuilder::create(TT, Argv);
232 }
233 
236  return IncrementalCompilerBuilder::createCuda(true);
237 }
238 
241  return IncrementalCompilerBuilder::createCuda(false);
242 }
243 
244 Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI,
245  llvm::Error &ErrOut,
246  std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder)
247  : JITBuilder(std::move(JITBuilder)) {
248  llvm::ErrorAsOutParameter EAO(&ErrOut);
249  auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
250  TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));
251  IncrParser = std::make_unique<IncrementalParser>(
252  *this, std::move(CI), *TSCtx->getContext(), ErrOut);
253  if (ErrOut)
254  return;
255 
256  // Not all frontends support code-generation, e.g. ast-dump actions don't
257  if (IncrParser->getCodeGen()) {
258  if (llvm::Error Err = CreateExecutor()) {
259  ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
260  return;
261  }
262 
263  // Process the PTUs that came from initialization. For example -include will
264  // give us a header that's processed at initialization of the preprocessor.
265  for (PartialTranslationUnit &PTU : IncrParser->getPTUs())
266  if (llvm::Error Err = Execute(PTU)) {
267  ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
268  return;
269  }
270  }
271 }
272 
274  if (IncrExecutor) {
275  if (llvm::Error Err = IncrExecutor->cleanUp())
276  llvm::report_fatal_error(
277  llvm::Twine("Failed to clean up IncrementalExecutor: ") +
278  toString(std::move(Err)));
279  }
280 }
281 
282 // These better to put in a runtime header but we can't. This is because we
283 // can't find the precise resource directory in unittests so we have to hard
284 // code them.
285 const char *const Runtimes = R"(
286  #define __CLANG_REPL__ 1
287 #ifdef __cplusplus
288  #define EXTERN_C extern "C"
289  void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
290  struct __clang_Interpreter_NewTag{} __ci_newtag;
291  void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept;
292  template <class T, class = T (*)() /*disable for arrays*/>
293  void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) {
294  for (auto Idx = 0; Idx < Size; ++Idx)
295  new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]);
296  }
297  template <class T, unsigned long N>
298  void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
299  __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
300  }
301 #else
302  #define EXTERN_C extern
303 #endif // __cplusplus
304 
305  EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...);
306 )";
307 
309 Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
310  llvm::Error Err = llvm::Error::success();
311  auto Interp =
312  std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
313  if (Err)
314  return std::move(Err);
315 
316  // Add runtime code and set a marker to hide it from user code. Undo will not
317  // go through that.
318  auto PTU = Interp->Parse(Runtimes);
319  if (!PTU)
320  return PTU.takeError();
321  Interp->markUserCodeStart();
322 
323  Interp->ValuePrintingInfo.resize(4);
324  return std::move(Interp);
325 }
326 
328 Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
329  std::unique_ptr<CompilerInstance> DCI) {
330  // avoid writing fat binary to disk using an in-memory virtual file system
332  std::make_unique<llvm::vfs::InMemoryFileSystem>();
334  std::make_unique<llvm::vfs::OverlayFileSystem>(
335  llvm::vfs::getRealFileSystem());
336  OverlayVFS->pushOverlay(IMVFS);
337  CI->createFileManager(OverlayVFS);
338 
339  auto Interp = Interpreter::create(std::move(CI));
340  if (auto E = Interp.takeError())
341  return std::move(E);
342 
343  llvm::Error Err = llvm::Error::success();
344  auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
345  **Interp, std::move(DCI), *(*Interp)->IncrParser.get(),
346  *(*Interp)->TSCtx->getContext(), IMVFS, Err);
347  if (Err)
348  return std::move(Err);
349 
350  (*Interp)->DeviceParser = std::move(DeviceParser);
351 
352  return Interp;
353 }
354 
356  return IncrParser->getCI();
357 }
358 
360  return IncrParser->getCI();
361 }
362 
364  if (!IncrExecutor) {
365  if (auto Err = CreateExecutor())
366  return std::move(Err);
367  }
368 
369  return IncrExecutor->GetExecutionEngine();
370 }
371 
374 }
375 
378 }
379 
380 void Interpreter::markUserCodeStart() {
381  assert(!InitPTUSize && "We only do this once");
382  InitPTUSize = IncrParser->getPTUs().size();
383 }
384 
385 size_t Interpreter::getEffectivePTUSize() const {
386  std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
387  assert(PTUs.size() >= InitPTUSize && "empty PTU list?");
388  return PTUs.size() - InitPTUSize;
389 }
390 
392 Interpreter::Parse(llvm::StringRef Code) {
393  // If we have a device parser, parse it first.
394  // The generated code will be included in the host compilation
395  if (DeviceParser) {
396  auto DevicePTU = DeviceParser->Parse(Code);
397  if (auto E = DevicePTU.takeError())
398  return std::move(E);
399  }
400 
401  // Tell the interpreter sliently ignore unused expressions since value
402  // printing could cause it.
404  clang::diag::warn_unused_expr, diag::Severity::Ignored, SourceLocation());
405  return IncrParser->Parse(Code);
406 }
407 
409 createJITTargetMachineBuilder(const std::string &TT) {
410  if (TT == llvm::sys::getProcessTriple())
411  // This fails immediately if the target backend is not registered
412  return llvm::orc::JITTargetMachineBuilder::detectHost();
413 
414  // If the target backend is not registered, LLJITBuilder::create() will fail
415  return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT));
416 }
417 
419  if (IncrExecutor)
420  return llvm::make_error<llvm::StringError>("Operation failed. "
421  "Execution engine exists",
422  std::error_code());
423  if (!IncrParser->getCodeGen())
424  return llvm::make_error<llvm::StringError>("Operation failed. "
425  "No code generator available",
426  std::error_code());
427  if (!JITBuilder) {
428  const std::string &TT = getCompilerInstance()->getTargetOpts().Triple;
429  auto JTMB = createJITTargetMachineBuilder(TT);
430  if (!JTMB)
431  return JTMB.takeError();
432  auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB));
433  if (!JB)
434  return JB.takeError();
435  JITBuilder = std::move(*JB);
436  }
437 
438  llvm::Error Err = llvm::Error::success();
439 #ifdef __EMSCRIPTEN__
440  auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
441 #else
442  auto Executor =
443  std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
444 #endif
445  if (!Err)
446  IncrExecutor = std::move(Executor);
447 
448  return Err;
449 }
450 
451 void Interpreter::ResetExecutor() { IncrExecutor.reset(); }
452 
454  assert(T.TheModule);
455  if (!IncrExecutor) {
456  auto Err = CreateExecutor();
457  if (Err)
458  return Err;
459  }
460  // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
461  if (auto Err = IncrExecutor->addModule(T))
462  return Err;
463 
464  if (auto Err = IncrExecutor->runCtors())
465  return Err;
466 
467  return llvm::Error::success();
468 }
469 
470 llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
471 
472  auto PTU = Parse(Code);
473  if (!PTU)
474  return PTU.takeError();
475  if (PTU->TheModule)
476  if (llvm::Error Err = Execute(*PTU))
477  return Err;
478 
479  if (LastValue.isValid()) {
480  if (!V) {
481  LastValue.dump();
482  LastValue.clear();
483  } else
484  *V = std::move(LastValue);
485  }
486  return llvm::Error::success();
487 }
488 
491  if (!IncrExecutor)
492  return llvm::make_error<llvm::StringError>("Operation failed. "
493  "No execution engine",
494  std::error_code());
495  llvm::StringRef MangledName = IncrParser->GetMangledName(GD);
496  return getSymbolAddress(MangledName);
497 }
498 
500 Interpreter::getSymbolAddress(llvm::StringRef IRName) const {
501  if (!IncrExecutor)
502  return llvm::make_error<llvm::StringError>("Operation failed. "
503  "No execution engine",
504  std::error_code());
505 
506  return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName);
507 }
508 
510 Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const {
511  if (!IncrExecutor)
512  return llvm::make_error<llvm::StringError>("Operation failed. "
513  "No execution engine",
514  std::error_code());
515 
516  return IncrExecutor->getSymbolAddress(Name, IncrementalExecutor::LinkerName);
517 }
518 
519 llvm::Error Interpreter::Undo(unsigned N) {
520 
521  std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
522  if (N > getEffectivePTUSize())
523  return llvm::make_error<llvm::StringError>("Operation failed. "
524  "Too many undos",
525  std::error_code());
526  for (unsigned I = 0; I < N; I++) {
527  if (IncrExecutor) {
528  if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back()))
529  return Err;
530  }
531 
532  IncrParser->CleanUpPTU(PTUs.back());
533  PTUs.pop_back();
534  }
535  return llvm::Error::success();
536 }
537 
538 llvm::Error Interpreter::LoadDynamicLibrary(const char *name) {
539  auto EE = getExecutionEngine();
540  if (!EE)
541  return EE.takeError();
542 
543  auto &DL = EE->getDataLayout();
544 
546  name, DL.getGlobalPrefix()))
547  EE->getMainJITDylib().addGenerator(std::move(*DLSG));
548  else
549  return DLSG.takeError();
550 
551  return llvm::Error::success();
552 }
553 
556  assert(CXXRD && "Cannot compile a destructor for a nullptr");
557  if (auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end())
558  return Dtor->getSecond();
559 
560  if (CXXRD->hasIrrelevantDestructor())
561  return llvm::orc::ExecutorAddr{};
562 
563  CXXDestructorDecl *DtorRD =
565 
566  llvm::StringRef Name =
567  IncrParser->GetMangledName(GlobalDecl(DtorRD, Dtor_Base));
568  auto AddrOrErr = getSymbolAddress(Name);
569  if (!AddrOrErr)
570  return AddrOrErr.takeError();
571 
572  Dtors[CXXRD] = *AddrOrErr;
573  return AddrOrErr;
574 }
575 
576 static constexpr llvm::StringRef MagicRuntimeInterface[] = {
577  "__clang_Interpreter_SetValueNoAlloc",
578  "__clang_Interpreter_SetValueWithAlloc",
579  "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"};
580 
581 static std::unique_ptr<RuntimeInterfaceBuilder>
583  Sema &S);
584 
585 std::unique_ptr<RuntimeInterfaceBuilder> Interpreter::FindRuntimeInterface() {
586  if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; }))
587  return nullptr;
588 
589  Sema &S = getCompilerInstance()->getSema();
590  ASTContext &Ctx = S.getASTContext();
591 
592  auto LookupInterface = [&](Expr *&Interface, llvm::StringRef Name) {
593  LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(),
597  if (R.empty())
598  return false;
599 
600  CXXScopeSpec CSS;
601  Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get();
602  return true;
603  };
604 
605  if (!LookupInterface(ValuePrintingInfo[NoAlloc],
607  return nullptr;
608  if (Ctx.getLangOpts().CPlusPlus) {
609  if (!LookupInterface(ValuePrintingInfo[WithAlloc],
611  return nullptr;
612  if (!LookupInterface(ValuePrintingInfo[CopyArray],
614  return nullptr;
615  if (!LookupInterface(ValuePrintingInfo[NewTag],
617  return nullptr;
618  }
619 
620  return createInProcessRuntimeInterfaceBuilder(*this, Ctx, S);
621 }
622 
623 namespace {
624 
625 class InterfaceKindVisitor
626  : public TypeVisitor<InterfaceKindVisitor, Interpreter::InterfaceKind> {
627  friend class InProcessRuntimeInterfaceBuilder;
628 
629  ASTContext &Ctx;
630  Sema &S;
631  Expr *E;
633 
634 public:
635  InterfaceKindVisitor(ASTContext &Ctx, Sema &S, Expr *E)
636  : Ctx(Ctx), S(S), E(E) {}
637 
638  Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) {
639  return Interpreter::InterfaceKind::WithAlloc;
640  }
641 
643  VisitMemberPointerType(const MemberPointerType *Ty) {
644  return Interpreter::InterfaceKind::WithAlloc;
645  }
646 
648  VisitConstantArrayType(const ConstantArrayType *Ty) {
650  }
651 
653  VisitFunctionProtoType(const FunctionProtoType *Ty) {
654  HandlePtrType(Ty);
655  return Interpreter::InterfaceKind::NoAlloc;
656  }
657 
658  Interpreter::InterfaceKind VisitPointerType(const PointerType *Ty) {
659  HandlePtrType(Ty);
660  return Interpreter::InterfaceKind::NoAlloc;
661  }
662 
663  Interpreter::InterfaceKind VisitReferenceType(const ReferenceType *Ty) {
664  ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, E);
665  assert(!AddrOfE.isInvalid() && "Can not create unary expression");
666  Args.push_back(AddrOfE.get());
667  return Interpreter::InterfaceKind::NoAlloc;
668  }
669 
670  Interpreter::InterfaceKind VisitBuiltinType(const BuiltinType *Ty) {
671  if (Ty->isNullPtrType())
672  Args.push_back(E);
673  else if (Ty->isFloatingType())
674  Args.push_back(E);
675  else if (Ty->isIntegralOrEnumerationType())
676  HandleIntegralOrEnumType(Ty);
677  else if (Ty->isVoidType()) {
678  // Do we need to still run `E`?
679  }
680 
681  return Interpreter::InterfaceKind::NoAlloc;
682  }
683 
684  Interpreter::InterfaceKind VisitEnumType(const EnumType *Ty) {
685  HandleIntegralOrEnumType(Ty);
686  return Interpreter::InterfaceKind::NoAlloc;
687  }
688 
689 private:
690  // Force cast these types to the uint that fits the register size. That way we
691  // reduce the number of overloads of `__clang_Interpreter_SetValueNoAlloc`.
692  void HandleIntegralOrEnumType(const Type *Ty) {
693  uint64_t PtrBits = Ctx.getTypeSize(Ctx.VoidPtrTy);
694  QualType UIntTy = Ctx.getBitIntType(/*Unsigned=*/true, PtrBits);
695  TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(UIntTy);
696  ExprResult CastedExpr =
698  assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr");
699  Args.push_back(CastedExpr.get());
700  }
701 
702  void HandlePtrType(const Type *Ty) {
704  ExprResult CastedExpr =
706  assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression");
707  Args.push_back(CastedExpr.get());
708  }
709 };
710 
711 class InProcessRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder {
712  Interpreter &Interp;
713  ASTContext &Ctx;
714  Sema &S;
715 
716 public:
717  InProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &C, Sema &S)
718  : Interp(Interp), Ctx(C), S(S) {}
719 
720  TransformExprFunction *getPrintValueTransformer() override {
721  return &transformForValuePrinting;
722  }
723 
724 private:
725  static ExprResult transformForValuePrinting(RuntimeInterfaceBuilder *Builder,
726  Expr *E,
727  ArrayRef<Expr *> FixedArgs) {
728  auto *B = static_cast<InProcessRuntimeInterfaceBuilder *>(Builder);
729 
730  // Get rid of ExprWithCleanups.
731  if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E))
732  E = EWC->getSubExpr();
733 
734  InterfaceKindVisitor Visitor(B->Ctx, B->S, E);
735 
736  // The Interpreter* parameter and the out parameter `OutVal`.
737  for (Expr *E : FixedArgs)
738  Visitor.Args.push_back(E);
739 
740  QualType Ty = E->getType();
741  QualType DesugaredTy = Ty.getDesugaredType(B->Ctx);
742 
743  // For lvalue struct, we treat it as a reference.
744  if (DesugaredTy->isRecordType() && E->isLValue()) {
745  DesugaredTy = B->Ctx.getLValueReferenceType(DesugaredTy);
746  Ty = B->Ctx.getLValueReferenceType(Ty);
747  }
748 
749  Expr *TypeArg = CStyleCastPtrExpr(B->S, B->Ctx.VoidPtrTy,
750  (uintptr_t)Ty.getAsOpaquePtr());
751  // The QualType parameter `OpaqueType`, represented as `void*`.
752  Visitor.Args.push_back(TypeArg);
753 
754  // We push the last parameter based on the type of the Expr. Note we need
755  // special care for rvalue struct.
756  Interpreter::InterfaceKind Kind = Visitor.Visit(&*DesugaredTy);
757  switch (Kind) {
758  case Interpreter::InterfaceKind::WithAlloc:
760  // __clang_Interpreter_SetValueWithAlloc.
761  ExprResult AllocCall = B->S.ActOnCallExpr(
762  /*Scope=*/nullptr,
763  B->Interp
764  .getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc],
765  E->getBeginLoc(), Visitor.Args, E->getEndLoc());
766  assert(!AllocCall.isInvalid() && "Can't create runtime interface call!");
767 
768  TypeSourceInfo *TSI =
769  B->Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation());
770 
771  // Force CodeGen to emit destructor.
772  if (auto *RD = Ty->getAsCXXRecordDecl()) {
773  auto *Dtor = B->S.LookupDestructor(RD);
774  Dtor->addAttr(UsedAttr::CreateImplicit(B->Ctx));
775  B->Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl(
776  DeclGroupRef(Dtor));
777  }
778 
779  // __clang_Interpreter_SetValueCopyArr.
781  const auto *ConstantArrTy =
782  cast<ConstantArrayType>(DesugaredTy.getTypePtr());
783  size_t ArrSize = B->Ctx.getConstantArrayElementCount(ConstantArrTy);
784  Expr *ArrSizeExpr = IntegerLiteralExpr(B->Ctx, ArrSize);
785  Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr};
786  return B->S.ActOnCallExpr(
787  /*Scope *=*/nullptr,
788  B->Interp
789  .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray],
790  SourceLocation(), Args, SourceLocation());
791  }
792  Expr *Args[] = {
793  AllocCall.get(),
794  B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]};
795  ExprResult CXXNewCall = B->S.BuildCXXNew(
796  E->getSourceRange(),
797  /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args,
798  /*PlacementRParen=*/SourceLocation(),
799  /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt,
800  E->getSourceRange(), E);
801 
802  assert(!CXXNewCall.isInvalid() &&
803  "Can't create runtime placement new call!");
804 
805  return B->S.ActOnFinishFullExpr(CXXNewCall.get(),
806  /*DiscardedValue=*/false);
807  }
808  // __clang_Interpreter_SetValueNoAlloc.
809  case Interpreter::InterfaceKind::NoAlloc: {
810  return B->S.ActOnCallExpr(
811  /*Scope=*/nullptr,
812  B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc],
813  E->getBeginLoc(), Visitor.Args, E->getEndLoc());
814  }
815  default:
816  llvm_unreachable("Unhandled Interpreter::InterfaceKind");
817  }
818  }
819 };
820 } // namespace
821 
822 static std::unique_ptr<RuntimeInterfaceBuilder>
824  Sema &S) {
825  return std::make_unique<InProcessRuntimeInterfaceBuilder>(Interp, Ctx, S);
826 }
827 
828 // This synthesizes a call expression to a speciall
829 // function that is responsible for generating the Value.
830 // In general, we transform:
831 // clang-repl> x
832 // To:
833 // // 1. If x is a built-in type like int, float.
834 // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x);
835 // // 2. If x is a struct, and a lvalue.
836 // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType,
837 // &x);
838 // // 3. If x is a struct, but a rvalue.
839 // new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue,
840 // xQualType)) (x);
841 
843  Sema &S = getCompilerInstance()->getSema();
844  ASTContext &Ctx = S.getASTContext();
845 
846  if (!RuntimeIB) {
847  RuntimeIB = FindRuntimeInterface();
848  AddPrintValueCall = RuntimeIB->getPrintValueTransformer();
849  }
850 
851  assert(AddPrintValueCall &&
852  "We don't have a runtime interface for pretty print!");
853 
854  // Create parameter `ThisInterp`.
855  auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this);
856 
857  // Create parameter `OutVal`.
858  auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue);
859 
860  // Build `__clang_Interpreter_SetValue*` call.
861  ExprResult Result =
862  AddPrintValueCall(RuntimeIB.get(), E, {ThisInterp, OutValue});
863 
864  // It could fail, like printing an array type in C. (not supported)
865  if (Result.isInvalid())
866  return E;
867  return Result.get();
868 }
869 
870 // Temporary rvalue struct that need special care.
873  void *OpaqueType) {
874  Value &VRef = *(Value *)OutVal;
875  VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
876  return VRef.getPtr();
877 }
878 
880  void *This, void *OutVal, void *OpaqueType, ...) {
881  Value &VRef = *(Value *)OutVal;
882  Interpreter *I = static_cast<Interpreter *>(This);
883  VRef = Value(I, OpaqueType);
884  if (VRef.isVoid())
885  return;
886 
887  va_list args;
888  va_start(args, /*last named param*/ OpaqueType);
889 
890  QualType QT = VRef.getType();
891  if (VRef.getKind() == Value::K_PtrOrObj) {
892  VRef.setPtr(va_arg(args, void *));
893  } else {
894  if (const auto *ET = QT->getAs<EnumType>())
895  QT = ET->getDecl()->getIntegerType();
896  switch (QT->castAs<BuiltinType>()->getKind()) {
897  default:
898  llvm_unreachable("unknown type kind!");
899  break;
900  // Types shorter than int are resolved as int, else va_arg has UB.
901  case BuiltinType::Bool:
902  VRef.setBool(va_arg(args, int));
903  break;
904  case BuiltinType::Char_S:
905  VRef.setChar_S(va_arg(args, int));
906  break;
907  case BuiltinType::SChar:
908  VRef.setSChar(va_arg(args, int));
909  break;
910  case BuiltinType::Char_U:
911  VRef.setChar_U(va_arg(args, unsigned));
912  break;
913  case BuiltinType::UChar:
914  VRef.setUChar(va_arg(args, unsigned));
915  break;
916  case BuiltinType::Short:
917  VRef.setShort(va_arg(args, int));
918  break;
919  case BuiltinType::UShort:
920  VRef.setUShort(va_arg(args, unsigned));
921  break;
922  case BuiltinType::Int:
923  VRef.setInt(va_arg(args, int));
924  break;
925  case BuiltinType::UInt:
926  VRef.setUInt(va_arg(args, unsigned));
927  break;
928  case BuiltinType::Long:
929  VRef.setLong(va_arg(args, long));
930  break;
931  case BuiltinType::ULong:
932  VRef.setULong(va_arg(args, unsigned long));
933  break;
934  case BuiltinType::LongLong:
935  VRef.setLongLong(va_arg(args, long long));
936  break;
937  case BuiltinType::ULongLong:
938  VRef.setULongLong(va_arg(args, unsigned long long));
939  break;
940  // Types shorter than double are resolved as double, else va_arg has UB.
941  case BuiltinType::Float:
942  VRef.setFloat(va_arg(args, double));
943  break;
944  case BuiltinType::Double:
945  VRef.setDouble(va_arg(args, double));
946  break;
947  case BuiltinType::LongDouble:
948  VRef.setLongDouble(va_arg(args, long double));
949  break;
950  // See REPL_BUILTIN_TYPES.
951  }
952  }
953  va_end(args);
954 }
955 
956 // A trampoline to work around the fact that operator placement new cannot
957 // really be forward declared due to libc++ and libstdc++ declaration mismatch.
958 // FIXME: __clang_Interpreter_NewTag is ODR violation because we get the same
959 // definition in the interpreter runtime. We should move it in a runtime header
960 // which gets included by the interpreter and here.
963 operator new(size_t __sz, void *__p, __clang_Interpreter_NewTag) noexcept {
964  // Just forward to the standard operator placement new.
965  return operator new(__sz, __p);
966 }
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3346
enum clang::sema::@1659::IndirectLocalPathEntry::EntryKind Kind
Expr * E
CompileCommand Cmd
#define REPL_EXTERNAL_VISIBILITY
Definition: Value.h:72
static std::unique_ptr< RuntimeInterfaceBuilder > createInProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &Ctx, Sema &S)
static llvm::Expected< llvm::orc::JITTargetMachineBuilder > createJITTargetMachineBuilder(const std::string &TT)
const char *const Runtimes
REPL_EXTERNAL_VISIBILITY void * __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, void *OpaqueType)
void REPL_EXTERNAL_VISIBILITY __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,...)
static constexpr llvm::StringRef MagicRuntimeInterface[]
@ ForVisibleRedeclaration
The lookup results will be used for redeclaration of a name, if an entity by that name already exists...
#define va_arg(ap, type)
#define va_start(ap, param)
#define va_end(ap)
__builtin_va_list va_list
static __inline__ uint32_t volatile uint32_t * __p
Definition: arm_acle.h:88
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:187
CanQualType VoidPtrTy
Definition: ASTContext.h:1146
IdentifierTable & Idents
Definition: ASTContext.h:660
const LangOptions & getLangOpts() const
Definition: ASTContext.h:797
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2399
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:1101
QualType getBitIntType(bool Unsigned, unsigned NumBits) const
Return a bit-precise integer type with the specified signedness and bit count.
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
This class is used for builtin types like 'int'.
Definition: Type.h:3029
Kind getKind() const
Definition: Type.h:3081
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2803
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
bool hasIrrelevantDestructor() const
Determine whether this class has a destructor which has no semantic effect.
Definition: DeclCXX.h:1407
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:74
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
ASTContext & getASTContext() const
TargetOptions & getTargetOpts()
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
static std::string GetResourcesPath(const char *Argv0, void *MainAddr)
Get the directory where the compiler headers reside, relative to the compiler binary (found by the pa...
static bool CreateFromArgs(CompilerInvocation &Res, ArrayRef< const char * > CommandLineArgs, DiagnosticsEngine &Diags, const char *Argv0=nullptr)
Create a compiler invocation from a list of input options.
Represents the canonical version of C arrays with a specified constant size.
Definition: Type.h:3614
Used for handling and querying diagnostic IDs.
Options for controlling the compiler diagnostics engine.
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:193
void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc)
This allows the client to specify that certain warnings are ignored.
Definition: Diagnostic.cpp:354
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Definition: Type.h:6001
This represents one expression.
Definition: Expr.h:110
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition: Expr.h:277
QualType getType() const
Definition: Expr.h:142
Represents a prototype with parameter type info, e.g.
Definition: Type.h:5012
GlobalDecl - represents a global declaration.
Definition: GlobalDecl.h:56
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
llvm::Expected< std::unique_ptr< CompilerInstance > > CreateCudaHost()
llvm::Expected< std::unique_ptr< CompilerInstance > > CreateCpp()
llvm::Expected< std::unique_ptr< CompilerInstance > > CreateCudaDevice()
static llvm::Expected< std::unique_ptr< llvm::orc::LLJITBuilder > > createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB)
Provides top-level interfaces for incremental compilation and execution.
Definition: Interpreter.h:91
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddress(GlobalDecl GD) const
llvm::Error Execute(PartialTranslationUnit &T)
llvm::Expected< llvm::orc::LLJIT & > getExecutionEngine()
virtual ~Interpreter()
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const
static llvm::Expected< std::unique_ptr< Interpreter > > createWithCUDA(std::unique_ptr< CompilerInstance > CI, std::unique_ptr< CompilerInstance > DCI)
const CompilerInstance * getCompilerInstance() const
llvm::Expected< llvm::orc::ExecutorAddr > CompileDtorCall(CXXRecordDecl *CXXRD)
llvm::Error LoadDynamicLibrary(const char *name)
Link a dynamic library.
virtual std::unique_ptr< RuntimeInterfaceBuilder > FindRuntimeInterface()
llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V=nullptr)
Expr * SynthesizeExpr(Expr *E)
llvm::Error CreateExecutor()
Interpreter(std::unique_ptr< CompilerInstance > CI, llvm::Error &Err, std::unique_ptr< llvm::orc::LLJITBuilder > JITBuilder=nullptr)
static llvm::Expected< std::unique_ptr< Interpreter > > create(std::unique_ptr< CompilerInstance > CI)
llvm::Expected< PartialTranslationUnit & > Parse(llvm::StringRef Code)
llvm::Error Undo(unsigned N=1)
Undo N previous incremental inputs.
const ASTContext & getASTContext() const
Represents the results of name lookup.
Definition: Lookup.h:46
bool empty() const
Return true if no decls were found.
Definition: Lookup.h:362
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition: Type.h:3518
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3197
A (possibly-)qualified type.
Definition: Type.h:941
void * getAsOpaquePtr() const
Definition: Type.h:988
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
Definition: Type.h:1303
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:7760
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:5975
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:3438
Generate glue code between the Interpreter's built-in runtime and user code.
Definition: Interpreter.h:81
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:493
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15354
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition: Sema.h:9036
CXXDestructorDecl * LookupDestructor(CXXRecordDecl *Class)
Look for the destructor of the given class.
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
Definition: SemaCast.cpp:3360
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl=false)
Definition: SemaExpr.cpp:3236
ASTContext & getASTContext() const
Definition: Sema.h:560
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:350
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:338
static TargetInfo * CreateTargetInfo(DiagnosticsEngine &Diags, const std::shared_ptr< TargetOptions > &Opts)
Construct a target for the given options.
Definition: Targets.cpp:806
std::string Triple
The name of the target triple to compile for.
Definition: TargetOptions.h:29
void FlushDiagnostics(DiagnosticsEngine &Diags) const
FlushDiagnostics - Flush the buffered diagnostics to an given diagnostic engine.
A container of type source information.
Definition: Type.h:7731
QualType getType() const
Return the type wrapped by this type source info.
Definition: Type.h:7742
An operation on a type.
Definition: TypeVisitor.h:64
The base class of the type hierarchy.
Definition: Type.h:1829
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1882
bool isVoidType() const
Definition: Type.h:8347
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8635
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:8462
bool isFloatingType() const
Definition: Type.cpp:2249
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8568
bool isNullPtrType() const
Definition: Type.h:8380
bool isRecordType() const
Definition: Type.h:8113
QualType getType() const
Definition: Value.cpp:234
void dump() const
Definition: Value.cpp:256
void clear()
Definition: Value.cpp:218
void * getPtr() const
Definition: Value.cpp:229
bool isValid() const
Definition: Value.h:132
void setPtr(void *Ptr)
Definition: Value.h:141
@ K_PtrOrObj
Definition: Value.h:108
Kind getKind() const
Definition: Value.h:136
bool isVoid() const
Definition: Value.h:133
Command - An executable path/name and argument vector to execute.
Definition: Job.h:107
Compilation - A set of tasks to perform for a single driver invocation.
Definition: Compilation.h:45
const llvm::opt::DerivedArgList & getArgs() const
Definition: Compilation.h:201
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:77
JobList - A sequence of jobs to perform.
Definition: Job.h:302
size_type size() const
Definition: Job.h:327
void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo=nullptr) const
Definition: Job.cpp:475
iterator begin()
Definition: Job.h:328
Defines the clang::TargetInfo interface.
@ Ignored
Do not present this diagnostic, ignore it.
bool This(InterpState &S, CodePtr OpPC)
Definition: Interp.h:2268
bool CopyArray(InterpState &S, CodePtr OpPC, uint32_t SrcIndex, uint32_t DestIndex, uint32_t Size)
Definition: Interp.h:2486
bool Load(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1665
std::string toString(const til::SExpr *E)
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...
The JSON file list parser is used to communicate input to InstallAPI.
std::unique_ptr< DiagnosticOptions > CreateAndPopulateDiagOpts(ArrayRef< const char * > Argv)
OffloadArch
Definition: Cuda.h:55
IntegerLiteral * IntegerLiteralExpr(ASTContext &C, uint64_t Val)
@ Dtor_Base
Base object dtor.
Definition: ABI.h:36
const FunctionProtoType * T
Expr * CStyleCastPtrExpr(Sema &S, QualType Ty, Expr *E)
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
unsigned long uint64_t
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
The class keeps track of various objects created as part of processing incremental inputs.