clang 23.0.0git
CIRGenVTables.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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 contains code dealing with C++ code generation of virtual tables.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenVTables.h"
14
15#include "CIRGenCXXABI.h"
16#include "CIRGenModule.h"
17#include "mlir/IR/Types.h"
20#include "llvm/ADT/SmallVector.h"
21
22using namespace llvm;
23using namespace clang;
24using namespace clang::CIRGen;
25
27 : cgm(cgm), vtContext(cgm.getASTContext().getVTableContext()) {}
28
29cir::FuncOp CIRGenModule::getAddrOfThunk(StringRef name, mlir::Type fnTy,
30 GlobalDecl gd) {
31 return getOrCreateCIRFunction(name, fnTy, gd, /*forVTable=*/true,
32 /*dontDefer=*/true, /*isThunk=*/true);
33}
34
35static void setThunkProperties(CIRGenModule &cgm, const ThunkInfo &thunk,
36 cir::FuncOp thunkFn, bool forVTable,
37 GlobalDecl gd) {
38 cgm.setFunctionLinkage(gd, thunkFn);
39 cgm.getCXXABI().setThunkLinkage(thunkFn, forVTable, gd,
40 !thunk.Return.isEmpty());
41
42 // Set the right visibility.
43 cgm.setGVProperties(thunkFn, cast<NamedDecl>(gd.getDecl()));
44
45 if (!cgm.getCXXABI().exportThunk()) {
47 cgm.setDSOLocal(static_cast<mlir::Operation *>(thunkFn));
48 }
49
50 if (cgm.supportsCOMDAT() && thunkFn.isWeakForLinker())
51 thunkFn.setComdat(true);
52}
53
55 mlir::Type ptrTy = builder.getUInt8PtrTy();
57 return ptrTy;
58}
59
60mlir::Type CIRGenVTables::getVTableComponentType() {
61 return cgm.getVTableComponentType();
62}
63
64cir::RecordType CIRGenVTables::getVTableType(const VTableLayout &layout) {
66 mlir::Type componentType = getVTableComponentType();
67 for (unsigned i = 0, e = layout.getNumVTables(); i != e; ++i)
68 tys.push_back(cir::ArrayType::get(componentType, layout.getVTableSize(i)));
69
70 // FIXME(cir): should VTableLayout be encoded like we do for some
71 // AST nodes?
72 return cgm.getBuilder().getAnonRecordTy(tys, /*incomplete=*/false);
73}
74
75/// At this point in the translation unit, does it appear that can we
76/// rely on the vtable being defined elsewhere in the program?
77///
78/// The response is really only definitive when called at the end of
79/// the translation unit.
80///
81/// The only semantic restriction here is that the object file should
82/// not contain a vtable definition when that vtable is defined
83/// strongly elsewhere. Otherwise, we'd just like to avoid emitting
84/// vtables when unnecessary.
85/// TODO(cir): this should be merged into common AST helper for codegen.
87 assert(rd->isDynamicClass() && "Non-dynamic classes have no VTable.");
88
89 // We always synthesize vtables if they are needed in the MS ABI. MSVC doesn't
90 // emit them even if there is an explicit template instantiation.
91 if (cgm.getTarget().getCXXABI().isMicrosoft())
92 return false;
93
94 // If we have an explicit instantiation declaration (and not a
95 // definition), the vtable is defined elsewhere.
98 return true;
99
100 // Otherwise, if the class is an instantiated template, the
101 // vtable must be defined here.
102 if (tsk == TSK_ImplicitInstantiation ||
104 return false;
105
106 // Otherwise, if the class doesn't have a key function (possibly
107 // anymore), the vtable must be defined here.
108 const CXXMethodDecl *keyFunction =
110 if (!keyFunction)
111 return false;
112
113 // Otherwise, if we don't have a definition of the key function, the
114 // vtable must be defined somewhere else.
115 return !keyFunction->hasBody();
116}
117
118/// This is a callback from Sema to tell us that a particular vtable is
119/// required to be emitted in this translation unit.
120///
121/// This is only called for vtables that _must_ be emitted (mainly due to key
122/// functions). For weak vtables, CodeGen tracks when they are needed and
123/// emits them as-needed.
125 vtables.generateClassData(rd);
126}
127
130
131 if (rd->getNumVBases())
132 cgm.getCXXABI().emitVirtualInheritanceTables(rd);
133
134 cgm.getCXXABI().emitVTableDefinitions(*this, rd);
135}
136
137mlir::Attribute CIRGenVTables::getVTableComponent(
138 const VTableLayout &layout, unsigned componentIndex, mlir::Attribute rtti,
139 unsigned &nextVTableThunkIndex, unsigned vtableAddressPoint,
140 bool vtableHasLocalLinkage) {
141 const VTableComponent &component = layout.vtable_components()[componentIndex];
142
143 CIRGenBuilderTy builder = cgm.getBuilder();
144
146
147 switch (component.getKind()) {
149 cgm.errorNYI("getVTableComponent: UnusedFunctionPointer");
150 return mlir::Attribute();
151
153 return builder.getConstPtrAttr(builder.getUInt8PtrTy(),
154 component.getVCallOffset().getQuantity());
155
157 return builder.getConstPtrAttr(builder.getUInt8PtrTy(),
158 component.getVBaseOffset().getQuantity());
159
161 return builder.getConstPtrAttr(builder.getUInt8PtrTy(),
162 component.getOffsetToTop().getQuantity());
163
165 assert((mlir::isa<cir::GlobalViewAttr>(rtti) ||
166 mlir::isa<cir::ConstPtrAttr>(rtti)) &&
167 "expected GlobalViewAttr or ConstPtrAttr");
168 return rtti;
169
173 GlobalDecl gd = component.getGlobalDecl(
175 cgm.getASTContext().getLangOpts()));
176
178
179 auto getSpecialVirtFn = [&](StringRef name) -> cir::FuncOp {
181
182 if (cgm.getLangOpts().OpenMP && cgm.getLangOpts().OpenMPIsTargetDevice &&
183 cgm.getTriple().isNVPTX())
184 cgm.errorNYI(gd.getDecl()->getSourceRange(),
185 "getVTableComponent for OMP Device NVPTX");
186
187 cir::FuncType fnTy =
188 cgm.getBuilder().getFuncType({}, cgm.getBuilder().getVoidTy());
189 cir::FuncOp fnPtr = cgm.createRuntimeFunction(fnTy, name);
190
192 return fnPtr;
193 };
194
195 cir::FuncOp fnPtr;
196 if (cast<CXXMethodDecl>(gd.getDecl())->isPureVirtual()) {
197 if (!pureVirtualFn)
198 pureVirtualFn =
199 getSpecialVirtFn(cgm.getCXXABI().getPureVirtualCallName());
200 fnPtr = pureVirtualFn;
201 } else if (cast<CXXMethodDecl>(gd.getDecl())->isDeleted()) {
202 if (!deletedVirtualFn)
203 deletedVirtualFn =
204 getSpecialVirtFn(cgm.getCXXABI().getDeletedVirtualCallName());
205 fnPtr = deletedVirtualFn;
206 } else if (nextVTableThunkIndex < layout.vtable_thunks().size() &&
207 layout.vtable_thunks()[nextVTableThunkIndex].first ==
208 componentIndex) {
209 const ThunkInfo &thunkInfo =
210 layout.vtable_thunks()[nextVTableThunkIndex].second;
211 nextVTableThunkIndex++;
212 fnPtr = maybeEmitThunk(gd, thunkInfo, /*forVTable=*/true);
214 } else {
215 // Otherwise we can use the method definition directly.
216 cir::FuncType fnTy = cgm.getTypes().getFunctionTypeForVTable(gd);
217 fnPtr = cgm.getAddrOfFunction(gd, fnTy, /*ForVTable=*/true);
218 }
219
220 return cir::GlobalViewAttr::get(
221 builder.getUInt8PtrTy(),
222 mlir::FlatSymbolRefAttr::get(fnPtr.getSymNameAttr()));
223 }
224 }
225
226 llvm_unreachable("Unexpected vtable component kind");
227}
228
229void CIRGenVTables::createVTableInitializer(cir::GlobalOp &vtableOp,
230 const clang::VTableLayout &layout,
231 mlir::Attribute rtti,
232 bool vtableHasLocalLinkage) {
233 mlir::Type componentType = getVTableComponentType();
234
235 const llvm::SmallVectorImpl<unsigned> &addressPoints =
236 layout.getAddressPointIndices();
237 unsigned nextVTableThunkIndex = 0;
238
239 mlir::MLIRContext *mlirContext = &cgm.getMLIRContext();
240
242 for (auto [vtableIndex, addressPoint] : llvm::enumerate(addressPoints)) {
243 // Build a ConstArrayAttr of the vtable components.
244 size_t vtableStart = layout.getVTableOffset(vtableIndex);
245 size_t vtableEnd = vtableStart + layout.getVTableSize(vtableIndex);
247 components.reserve(vtableEnd - vtableStart);
248 for (size_t componentIndex : llvm::seq(vtableStart, vtableEnd))
249 components.push_back(
250 getVTableComponent(layout, componentIndex, rtti, nextVTableThunkIndex,
251 addressPoint, vtableHasLocalLinkage));
252 // Create a ConstArrayAttr to hold the components.
253 auto arr = cir::ConstArrayAttr::get(
254 cir::ArrayType::get(componentType, components.size()),
255 mlir::ArrayAttr::get(mlirContext, components));
256 vtables.push_back(arr);
257 }
258
259 // Create a ConstRecordAttr to hold the component array.
260 const auto members = mlir::ArrayAttr::get(mlirContext, vtables);
261 cir::ConstRecordAttr record = cgm.getBuilder().getAnonConstRecord(members);
262
263 // Create a VTableAttr
264 auto vtableAttr = cir::VTableAttr::get(record.getType(), record.getMembers());
265
266 // Add the vtable initializer to the vtable global op.
267 cgm.setInitializer(vtableOp, vtableAttr);
268}
269
271 const CXXRecordDecl *rd, const BaseSubobject &base, bool baseIsVirtual,
272 cir::GlobalLinkageKind linkage, VTableAddressPointsMapTy &addressPoints) {
274
275 std::unique_ptr<VTableLayout> vtLayout(
276 getItaniumVTableContext().createConstructionVTableLayout(
277 base.getBase(), base.getBaseOffset(), baseIsVirtual, rd));
278
279 // Add the address points.
280 addressPoints = vtLayout->getAddressPoints();
281
282 // Get the mangled construction vtable name.
283 SmallString<256> outName;
284 llvm::raw_svector_ostream out(outName);
285 cast<ItaniumMangleContext>(cgm.getCXXABI().getMangleContext())
286 .mangleCXXCtorVTable(rd, base.getBaseOffset().getQuantity(),
287 base.getBase(), out);
288 SmallString<256> name(outName);
289
291
292 cir::RecordType vtType = getVTableType(*vtLayout);
293
294 // Construction vtable symbols are not part of the Itanium ABI, so we cannot
295 // guarantee that they actually will be available externally. Instead, when
296 // emitting an available_externally VTT, we provide references to an internal
297 // linkage construction vtable. The ABI only requires complete-object vtables
298 // to be the same for all instances of a type, not construction vtables.
299 if (linkage == cir::GlobalLinkageKind::AvailableExternallyLinkage)
300 linkage = cir::GlobalLinkageKind::InternalLinkage;
301
302 llvm::Align align = cgm.getDataLayout().getABITypeAlign(vtType);
303 mlir::Location loc = cgm.getLoc(rd->getSourceRange());
304
305 // Create the variable that will hold the construction vtable.
306 cir::GlobalOp vtable = cgm.createOrReplaceCXXRuntimeVariable(
307 loc, name, vtType, linkage, CharUnits::fromQuantity(align));
308
309 // V-tables are always unnamed_addr.
311
312 mlir::Attribute rtti = cgm.getAddrOfRTTIDescriptor(
313 loc, cgm.getASTContext().getCanonicalTagType(base.getBase()));
314
315 // Create and set the initializer.
316 createVTableInitializer(vtable, *vtLayout, rtti,
317 cir::isLocalLinkage(vtable.getLinkage()));
318
319 // Set properties only after the initializer has been set to ensure that the
320 // GV is treated as definition and not declaration.
321 assert(!vtable.isDeclaration() && "Shouldn't set properties on declaration");
322 cgm.setGVProperties(vtable, rd);
323
326
327 return vtable;
328}
329
330/// Compute the required linkage of the vtable for the given class.
331///
332/// Note that we only call this at the end of the translation unit.
333cir::GlobalLinkageKind CIRGenModule::getVTableLinkage(const CXXRecordDecl *rd) {
334 if (!rd->isExternallyVisible())
335 return cir::GlobalLinkageKind::InternalLinkage;
336
337 // We're at the end of the translation unit, so the current key
338 // function is fully correct.
339 const CXXMethodDecl *keyFunction = astContext.getCurrentKeyFunction(rd);
340 if (keyFunction && !rd->hasAttr<DLLImportAttr>()) {
341 // If this class has a key function, use that to determine the
342 // linkage of the vtable.
343 const FunctionDecl *def = nullptr;
344 if (keyFunction->hasBody(def))
345 keyFunction = cast<CXXMethodDecl>(def);
346
347 // All of the cases below do something different with AppleKext enabled.
349 switch (keyFunction->getTemplateSpecializationKind()) {
350 case TSK_Undeclared:
352 assert(
353 (def || codeGenOpts.OptimizationLevel > 0 ||
354 codeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo) &&
355 "Shouldn't query vtable linkage without key function, "
356 "optimizations, or debug info");
357 if (!def && codeGenOpts.OptimizationLevel > 0)
358 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
359
360 if (keyFunction->isInlined())
361 return !astContext.getLangOpts().AppleKext
362 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
363 : cir::GlobalLinkageKind::InternalLinkage;
364 return cir::GlobalLinkageKind::ExternalLinkage;
365
367 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
368
370 return cir::GlobalLinkageKind::WeakODRLinkage;
371
373 llvm_unreachable("Should not have been asked to emit this");
374 }
375 }
376 // -fapple-kext mode does not support weak linkage, so we must use
377 // internal linkage.
378 if (astContext.getLangOpts().AppleKext)
379 return cir::GlobalLinkageKind::InternalLinkage;
380
381 auto discardableODRLinkage = cir::GlobalLinkageKind::LinkOnceODRLinkage;
382 auto nonDiscardableODRLinkage = cir::GlobalLinkageKind::WeakODRLinkage;
383 if (rd->hasAttr<DLLExportAttr>()) {
384 // Cannot discard exported vtables.
385 discardableODRLinkage = nonDiscardableODRLinkage;
386 } else if (rd->hasAttr<DLLImportAttr>()) {
387 // Imported vtables are available externally.
388 discardableODRLinkage = cir::GlobalLinkageKind::AvailableExternallyLinkage;
389 nonDiscardableODRLinkage =
390 cir::GlobalLinkageKind::AvailableExternallyLinkage;
391 }
392
393 switch (rd->getTemplateSpecializationKind()) {
394 case TSK_Undeclared:
397 return discardableODRLinkage;
398
401 "getVTableLinkage: explicit instantiation declaration");
402 return cir::GlobalLinkageKind::ExternalLinkage;
403 }
404
406 return nonDiscardableODRLinkage;
407 }
408
409 llvm_unreachable("Invalid TemplateSpecializationKind!");
410}
411
413 assert(rd->getNumVBases() && "Only classes with virtual bases need a VTT");
414
415 SmallString<256> outName;
416 llvm::raw_svector_ostream out(outName);
417 cast<ItaniumMangleContext>(cgm.getCXXABI().getMangleContext())
418 .mangleCXXVTT(rd, out);
419 StringRef name = outName.str();
420
421 // This will also defer the definition of the VTT.
422 (void)cgm.getCXXABI().getAddrOfVTable(rd, CharUnits());
423
424 VTTBuilder builder(cgm.getASTContext(), rd, /*GenerateDefinition=*/false);
425
426 auto arrayType = cir::ArrayType::get(cgm.getBuilder().getUInt8PtrTy(),
427 builder.getVTTComponents().size());
428 llvm::Align align =
429 cgm.getDataLayout().getABITypeAlign(cgm.getBuilder().getUInt8PtrTy());
430 cir::GlobalOp vtt = cgm.createOrReplaceCXXRuntimeVariable(
431 cgm.getLoc(rd->getSourceRange()), name, arrayType,
432 cir::GlobalLinkageKind::ExternalLinkage, CharUnits::fromQuantity(align));
433 cgm.setGVProperties(vtt, rd);
434 return vtt;
435}
436
437static cir::GlobalOp
439 const CXXRecordDecl *mostDerivedClass,
440 const VTTVTable &vtable, cir::GlobalLinkageKind linkage,
441 VTableLayout::AddressPointsMapTy &addressPoints) {
442 if (vtable.getBase() == mostDerivedClass) {
443 assert(vtable.getBaseOffset().isZero() &&
444 "Most derived class vtable must have a zero offset!");
445 // This is a regular vtable.
446 return cgm.getCXXABI().getAddrOfVTable(mostDerivedClass, CharUnits());
447 }
448 return cgvt.generateConstructionVTable(
449 mostDerivedClass, vtable.getBaseSubobject(), vtable.isVirtual(), linkage,
450 addressPoints);
451}
452
453/// Emit the definition of the given vtable.
454void CIRGenVTables::emitVTTDefinition(cir::GlobalOp vttOp,
455 cir::GlobalLinkageKind linkage,
456 const CXXRecordDecl *rd) {
457 VTTBuilder builder(cgm.getASTContext(), rd, /*GenerateDefinition=*/true);
458
459 mlir::MLIRContext *mlirContext = &cgm.getMLIRContext();
460
461 auto arrayType = cir::ArrayType::get(cgm.getBuilder().getUInt8PtrTy(),
462 builder.getVTTComponents().size());
463
465 SmallVector<VTableAddressPointsMapTy> vtableAddressPoints;
466 for (const VTTVTable &vtt : builder.getVTTVTables()) {
467 vtableAddressPoints.push_back(VTableAddressPointsMapTy());
468 vtables.push_back(getAddrOfVTTVTable(*this, cgm, rd, vtt, linkage,
469 vtableAddressPoints.back()));
470 }
471
472 SmallVector<mlir::Attribute> vttComponents;
473 for (const VTTComponent &vttComponent : builder.getVTTComponents()) {
474 const VTTVTable &vttVT = builder.getVTTVTables()[vttComponent.VTableIndex];
475 cir::GlobalOp vtable = vtables[vttComponent.VTableIndex];
477 if (vttVT.getBase() == rd) {
478 // Just get the address point for the regular vtable.
479 addressPoint =
481 vttComponent.VTableBase);
482 } else {
483 addressPoint = vtableAddressPoints[vttComponent.VTableIndex].lookup(
484 vttComponent.VTableBase);
485 assert(addressPoint.AddressPointIndex != 0 &&
486 "Did not find ctor vtable address point!");
487 }
488
489 mlir::Attribute indices[2] = {
490 cgm.getBuilder().getI32IntegerAttr(addressPoint.VTableIndex),
491 cgm.getBuilder().getI32IntegerAttr(addressPoint.AddressPointIndex),
492 };
493
494 auto indicesAttr = mlir::ArrayAttr::get(mlirContext, indices);
495 cir::GlobalViewAttr init = cgm.getBuilder().getGlobalViewAttr(
496 cgm.getBuilder().getUInt8PtrTy(), vtable, indicesAttr);
497
498 vttComponents.push_back(init);
499 }
500
501 auto init = cir::ConstArrayAttr::get(
502 arrayType, mlir::ArrayAttr::get(mlirContext, vttComponents));
503
504 vttOp.setInitialValueAttr(init);
505
506 // Set the correct linkage.
507 vttOp.setLinkage(linkage);
508 mlir::SymbolTable::setSymbolVisibility(
509 vttOp, CIRGenModule::getMLIRVisibility(vttOp));
510
511 if (cgm.supportsCOMDAT() && vttOp.isWeakForLinker())
512 vttOp.setComdat(true);
513}
514
516 BaseSubobject base) {
517 BaseSubobjectPairTy classSubobjectPair(rd, base);
518
519 SubVTTIndiciesMapTy::iterator it = subVTTIndicies.find(classSubobjectPair);
520 if (it != subVTTIndicies.end())
521 return it->second;
522
523 VTTBuilder builder(cgm.getASTContext(), rd, /*GenerateDefinition=*/false);
524
525 for (const auto &entry : builder.getSubVTTIndices()) {
526 // Insert all indices.
527 BaseSubobjectPairTy subclassSubobjectPair(rd, entry.first);
528
529 subVTTIndicies.insert(std::make_pair(subclassSubobjectPair, entry.second));
530 }
531
532 it = subVTTIndicies.find(classSubobjectPair);
533 assert(it != subVTTIndicies.end() && "Did not find index!");
534
535 return it->second;
536}
537
539 BaseSubobject base) {
540 auto it = secondaryVirtualPointerIndices.find(std::make_pair(rd, base));
541
542 if (it != secondaryVirtualPointerIndices.end())
543 return it->second;
544
545 VTTBuilder builder(cgm.getASTContext(), rd, /*GenerateDefinition=*/false);
546
547 // Insert all secondary vpointer indices.
548 for (const auto &entry : builder.getSecondaryVirtualPointerIndices()) {
549 std::pair<const CXXRecordDecl *, BaseSubobject> pair =
550 std::make_pair(rd, entry.first);
551
552 secondaryVirtualPointerIndices.insert(std::make_pair(pair, entry.second));
553 }
554
555 it = secondaryVirtualPointerIndices.find(std::make_pair(rd, base));
556 assert(it != secondaryVirtualPointerIndices.end() && "Did not find index!");
557
558 return it->second;
559}
560
562 RValue rv, const ThunkInfo &thunk) {
563 // Emit the return adjustment.
564 bool nullCheckValue = !resultType->isReferenceType();
565
566 mlir::Value returnValue = rv.getValue();
567
568 if (nullCheckValue)
569 cgf.cgm.errorNYI(
570 "return adjustment with null check for non-reference types");
571
572 const CXXRecordDecl *classDecl =
573 resultType->getPointeeType()->getAsCXXRecordDecl();
574 CharUnits classAlign = cgf.cgm.getClassPointerAlignment(classDecl);
575 mlir::Type pointeeType = cgf.convertTypeForMem(resultType->getPointeeType());
576 returnValue = cgf.cgm.getCXXABI().performReturnAdjustment(
577 cgf, Address(returnValue, pointeeType, classAlign), classDecl,
578 thunk.Return);
579
580 if (nullCheckValue)
581 cgf.cgm.errorNYI(
582 "return adjustment with null check for non-reference types");
583
584 return RValue::get(returnValue);
585}
586
588 const CIRGenFunctionInfo &fnInfo,
589 bool isUnprototyped) {
590 assert(!curGD.getDecl() && "curGD was already set!");
591 curGD = gd;
592 curFuncIsThunk = true;
593
594 // Build FunctionArgs.
595 const CXXMethodDecl *md = cast<CXXMethodDecl>(gd.getDecl());
596 QualType thisType = md->getThisType();
597 QualType resultType;
598 if (isUnprototyped)
599 resultType = cgm.getASTContext().VoidTy;
600 else if (cgm.getCXXABI().hasThisReturn(gd))
601 resultType = thisType;
602 else if (cgm.getCXXABI().hasMostDerivedReturn(gd))
603 resultType = cgm.getASTContext().VoidPtrTy;
604 else
605 resultType = md->getType()->castAs<FunctionProtoType>()->getReturnType();
606 FunctionArgList functionArgs;
607
608 // Create the implicit 'this' parameter declaration.
609 cgm.getCXXABI().buildThisParam(*this, functionArgs);
610
611 // Add the rest of the parameters, if we have a prototype to work with.
612 if (!isUnprototyped) {
613 functionArgs.append(md->param_begin(), md->param_end());
614
616 cgm.getCXXABI().addImplicitStructorParams(*this, resultType,
617 functionArgs);
618 }
619
621
622 // Start defining the function.
623 cir::FuncType funcType = cgm.getTypes().getFunctionType(fnInfo);
624 startFunction(GlobalDecl(), resultType, fn, funcType, functionArgs,
625 md->getLocation(), md->getLocation());
626 // TODO(cir): Move this into startFunction.
627 curFnInfo = &fnInfo;
629
630 // Since we didn't pass a GlobalDecl to startFunction, do this ourselves.
631 cgm.getCXXABI().emitInstanceFunctionProlog(md->getLocation(), *this);
633 curCodeDecl = md;
634 curFuncDecl = md;
635}
636
638 // Clear these to restore the invariants expected by
639 // startFunction/finishFunction.
640 curCodeDecl = nullptr;
641 curFuncDecl = nullptr;
642
644}
645
647 const ThunkInfo *thunk,
648 bool isUnprototyped) {
649 assert(isa<CXXMethodDecl>(curGD.getDecl()) &&
650 "Please use a new CGF for this thunk");
651 const CXXMethodDecl *md = cast<CXXMethodDecl>(curGD.getDecl());
652
653 // Determine the this pointer class (may differ from md's class for thunks).
654 const CXXRecordDecl *thisValueClass =
656 if (thunk)
657 thisValueClass = thunk->ThisType->getPointeeCXXRecordDecl();
658
659 mlir::Value adjustedThisPtr =
660 thunk ? cgm.getCXXABI().performThisAdjustment(*this, loadCXXThisAddress(),
661 thisValueClass, *thunk)
662 : loadCXXThis();
663
664 // If perfect forwarding is required a variadic method, a method using
665 // inalloca, or an unprototyped thunk, use musttail. Emit an error if this
666 // thunk requires a return adjustment, since that is impossible with musttail.
668 if ((curFnInfo && curFnInfo->isVariadic()) || isUnprototyped) {
669 // Error if return adjustment is needed (can't do with musttail).
670 if (thunk && !thunk->Return.isEmpty()) {
671 if (isUnprototyped)
672 cgm.errorUnsupported(
673 md, "return-adjusting thunk with incomplete parameter type");
674 else if (curFnInfo && curFnInfo->isVariadic())
675 llvm_unreachable("shouldn't try to emit musttail return-adjusting "
676 "thunks for variadic functions");
677 else
678 cgm.errorUnsupported(
679 md, "non-trivial argument copy for return-adjusting thunk");
680 }
681 emitMustTailThunk(curGD, adjustedThisPtr, callee);
682 return;
683 }
684
685 // Build the call argument list.
686 CallArgList callArgs;
687 QualType thisType = md->getThisType();
688 callArgs.add(RValue::get(adjustedThisPtr), thisType);
689
691 cgm.getCXXABI().adjustCallArgsForDestructorThunk(*this, curGD, callArgs);
692
693#ifndef NDEBUG
694 unsigned prefixArgs = callArgs.size() - 1;
695#endif
696
697 // Add the rest of the method parameters.
698 for (const ParmVarDecl *pd : md->parameters())
699 emitDelegateCallArg(callArgs, pd, SourceLocation());
700
701 const FunctionProtoType *fpt = md->getType()->castAs<FunctionProtoType>();
702
703#ifndef NDEBUG
704 const CIRGenFunctionInfo &callFnInfo = cgm.getTypes().arrangeCXXMethodCall(
705 callArgs, fpt, RequiredArgs::getFromProtoWithExtraSlots(fpt, 1),
706 prefixArgs);
707 assert(callFnInfo.argTypeSize() == curFnInfo->argTypeSize());
708#endif
709
710 // Determine whether we have a return value slot to use.
711 QualType resultType = cgm.getCXXABI().hasThisReturn(curGD) ? thisType
712 : cgm.getCXXABI().hasMostDerivedReturn(curGD)
713 ? cgm.getASTContext().VoidPtrTy
714 : fpt->getReturnType();
715
716 ReturnValueSlot slot;
717 // This should also be tracking volatile, unused, and externally destructed.
719 if (!resultType->isVoidType() && hasAggregateEvaluationKind(resultType))
721
722 // Now emit our call.
723 CIRGenCallee cirCallee = CIRGenCallee::forDirect(callee, curGD);
724 mlir::Location loc = builder.getUnknownLoc();
725 RValue rv = emitCall(*curFnInfo, cirCallee, slot, callArgs,
726 /*callOrTryCall=*/nullptr, loc);
727
728 // Consider return adjustment if we have ThunkInfo.
729 if (thunk && !thunk->Return.isEmpty())
730 rv = performReturnAdjustment(*this, resultType, rv, *thunk);
731 else
733
734 // Emit return.
735 if (!resultType->isVoidType() && slot.isNull())
736 cgm.getCXXABI().emitReturnFromThunk(*this, rv, resultType);
737
738 // Disable final ARC autorelease.
740
741 finishThunk();
742}
743
745 mlir::Value adjustedThisPtr,
746 cir::FuncOp callee) {
748 cgm.errorNYI("musttail thunk");
749}
750
752 const CIRGenFunctionInfo &fnInfo,
753 GlobalDecl gd, const ThunkInfo &thunk,
754 bool isUnprototyped) {
755 // Create entry block and set up the builder's insertion point.
756 // This must be done before calling startThunk() which calls startFunction().
757 assert(fn.isDeclaration() && "Function already has body?");
758 mlir::Block *entryBb = fn.addEntryBlock();
759 builder.setInsertionPointToStart(entryBb);
760
761 // Create a scope in the symbol table to hold variable declarations.
762 // This is required before startFunction processes parameters, as it will
763 // insert them into the symbolTable (ScopedHashTable) which requires an
764 // active scope.
766
767 // Create lexical scope - must stay alive for entire thunk generation.
768 // startFunction() requires currLexScope to be set.
769 SourceLocRAIIObject locRAII(*this, fn.getLoc());
770 LexicalScope lexScope{*this, fn.getLoc(), entryBb};
771
772 startThunk(fn, gd, fnInfo, isUnprototyped);
774
775 // Get our callee. Use a placeholder type if this method is unprototyped so
776 // that CIRGenModule doesn't try to set attributes.
777 mlir::Type ty;
778 if (isUnprototyped)
779 cgm.errorNYI("unprototyped thunk placeholder type");
780 else
781 ty = cgm.getTypes().getFunctionType(fnInfo);
782
783 cir::FuncOp calleeOp = cgm.getAddrOfFunction(gd, ty, /*forVTable=*/true);
784
785 // Make the call and return the result.
786 emitCallAndReturnForThunk(calleeOp, &thunk, isUnprototyped);
787}
788
790 bool isUnprototyped, bool forVTable) {
791 // Always emit thunks in the MS C++ ABI. We cannot rely on other TUs to
792 // provide thunks for us.
793 if (cgm.getTarget().getCXXABI().isMicrosoft())
794 return true;
795
796 // In the Itanium C++ ABI, vtable thunks are provided by TUs that provide
797 // definitions of the main method. Therefore, emitting thunks with the vtable
798 // is purely an optimization. Emit the thunk if optimizations are enabled and
799 // all of the parameter types are complete.
800 if (forVTable)
801 return cgm.getCodeGenOpts().OptimizationLevel && !isUnprototyped;
802
803 // Always emit thunks along with the method definition.
804 return true;
805}
806
808 const ThunkInfo &thunkAdjustments,
809 bool forVTable) {
810 const CXXMethodDecl *md = cast<CXXMethodDecl>(gd.getDecl());
811 SmallString<256> name;
812 MangleContext &mCtx = cgm.getCXXABI().getMangleContext();
813
814 llvm::raw_svector_ostream out(name);
815 if (const CXXDestructorDecl *dd = dyn_cast<CXXDestructorDecl>(md)) {
816 mCtx.mangleCXXDtorThunk(dd, gd.getDtorType(), thunkAdjustments,
817 /*elideOverrideInfo=*/false, out);
818 } else {
819 mCtx.mangleThunk(md, thunkAdjustments, /*elideOverrideInfo=*/false, out);
820 }
821
822 if (cgm.getASTContext().useAbbreviatedThunkName(gd, name.str())) {
823 name = "";
824 if (const CXXDestructorDecl *dd = dyn_cast<CXXDestructorDecl>(md))
825 mCtx.mangleCXXDtorThunk(dd, gd.getDtorType(), thunkAdjustments,
826 /*elideOverrideInfo=*/true, out);
827 else
828 mCtx.mangleThunk(md, thunkAdjustments, /*elideOverrideInfo=*/true, out);
829 }
830
831 cir::FuncType thunkVTableTy = cgm.getTypes().getFunctionTypeForVTable(gd);
832 cir::FuncOp thunk = cgm.getAddrOfThunk(name, thunkVTableTy, gd);
833
834 // If we don't need to emit a definition, return this declaration as is.
835 bool isUnprototyped = !cgm.getTypes().isFuncTypeConvertible(
836 md->getType()->castAs<FunctionType>());
837 if (!shouldEmitVTableThunk(cgm, md, isUnprototyped, forVTable))
838 return thunk;
839
840 // Arrange a function prototype appropriate for a function definition. In some
841 // cases in the MS ABI, we may need to build an unprototyped musttail thunk.
842 const CIRGenFunctionInfo &fnInfo =
843 isUnprototyped ? (cgm.errorNYI("unprototyped must-tail thunk"),
844 cgm.getTypes().arrangeGlobalDeclaration(gd))
845 : cgm.getTypes().arrangeGlobalDeclaration(gd);
846 cir::FuncType thunkFnTy = cgm.getTypes().getFunctionType(fnInfo);
847
848 // This is to replace OG's casting to a function, keeping it here to
849 // streamline the 1-to-1 mapping from OG starting below.
850 cir::FuncOp thunkFn = thunk;
851 if (thunk.getFunctionType() != thunkFnTy) {
852 cir::FuncOp oldThunkFn = thunkFn;
853
854 assert(oldThunkFn.isDeclaration() && "Shouldn't replace non-declaration");
855
856 // Remove the name from the old thunk function and get a new thunk.
857 oldThunkFn.setName(StringRef());
858 thunkFn =
859 cir::FuncOp::create(cgm.getBuilder(), thunk->getLoc(), name.str(),
860 thunkFnTy, cir::GlobalLinkageKind::ExternalLinkage);
861 cgm.setCIRFunctionAttributes(md, fnInfo, thunkFn, /*isThunk=*/false);
862
863 if (!oldThunkFn->use_empty())
864 oldThunkFn->replaceAllUsesWith(thunkFn);
865
866 // Remove the old thunk.
867 oldThunkFn->erase();
868 }
869
870 bool abiHasKeyFunctions = cgm.getTarget().getCXXABI().hasKeyFunctions();
871 bool useAvailableExternallyLinkage = forVTable && abiHasKeyFunctions;
872
873 // If the type of the underlying GlobalValue is wrong, we'll have to replace
874 // it. It should be a declaration.
875 if (!thunkFn.isDeclaration()) {
876 if (!abiHasKeyFunctions || useAvailableExternallyLinkage) {
877 // There is already a thunk emitted for this function, do nothing.
878 return thunkFn;
879 }
880
881 setThunkProperties(cgm, thunkAdjustments, thunkFn, forVTable, gd);
882 return thunkFn;
883 }
884
885 // TODO(cir): Add "thunk" attribute if unprototyped.
886
887 cgm.setCIRFunctionAttributesForDefinition(cast<FunctionDecl>(gd.getDecl()),
888 thunkFn);
889
890 // Thunks for variadic methods are special because in general variadic
891 // arguments cannot be perfectly forwarded. In the general case, clang
892 // implements such thunks by cloning the original function body. However, for
893 // thunks with no return adjustment on targets that support musttail, we can
894 // use musttail to perfectly forward the variadic arguments.
895 bool shouldCloneVarArgs = false;
896 if (!isUnprototyped && thunkFn.getFunctionType().isVarArg()) {
897 shouldCloneVarArgs = true;
898 if (thunkAdjustments.Return.isEmpty()) {
899 switch (cgm.getTriple().getArch()) {
900 case llvm::Triple::x86_64:
901 case llvm::Triple::x86:
902 case llvm::Triple::aarch64:
903 shouldCloneVarArgs = false;
904 break;
905 default:
906 break;
907 }
908 }
909 }
910
911 if (shouldCloneVarArgs) {
912 if (useAvailableExternallyLinkage)
913 return thunkFn;
914 cgm.errorNYI("varargs thunk cloning");
915 } else {
916 // Normal thunk body generation.
917 mlir::OpBuilder::InsertionGuard guard(cgm.getBuilder());
918 CIRGenFunction cgf(cgm, cgm.getBuilder());
919 cgf.generateThunk(thunkFn, fnInfo, gd, thunkAdjustments, isUnprototyped);
920 }
921
922 setThunkProperties(cgm, thunkAdjustments, thunkFn, forVTable, gd);
923 return thunkFn;
924}
925
927 const CXXMethodDecl *md =
928 cast<CXXMethodDecl>(gd.getDecl())->getCanonicalDecl();
929
930 // We don't need to generate thunks for the base destructor.
932 return;
933
934 const VTableContextBase::ThunkInfoVectorTy *thunkInfoVector =
935 vtContext->getThunkInfo(gd);
936
937 if (!thunkInfoVector)
938 return;
939
940 for (const ThunkInfo &thunk : *thunkInfoVector)
941 maybeEmitThunk(gd, thunk, /*forVTable=*/false);
942}
static RValue performReturnAdjustment(CIRGenFunction &cgf, QualType resultType, RValue rv, const ThunkInfo &thunk)
static cir::GlobalOp getAddrOfVTTVTable(CIRGenVTables &cgvt, CIRGenModule &cgm, const CXXRecordDecl *mostDerivedClass, const VTTVTable &vtable, cir::GlobalLinkageKind linkage, VTableLayout::AddressPointsMapTy &addressPoints)
static void setThunkProperties(CIRGenModule &cgm, const ThunkInfo &thunk, cir::FuncOp thunkFn, bool forVTable, GlobalDecl gd)
static bool shouldEmitVTableThunk(CIRGenModule &cgm, const CXXMethodDecl *md, bool isUnprototyped, bool forVTable)
mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value)
const CXXMethodDecl * getCurrentKeyFunction(const CXXRecordDecl *RD)
Get our current best idea for the key function of the given record decl, or nullptr if there isn't on...
const LangOptions & getLangOpts() const
Definition ASTContext.h:951
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:916
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
cir::PointerType getUInt8PtrTy()
cir::FuncType getFuncType(llvm::ArrayRef< mlir::Type > params, mlir::Type retTy, bool isVarArg=false)
virtual bool exportThunk()=0
Returns true if the thunk should be exported.
virtual cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd, CharUnits vptrOffset)=0
Get the address of the vtable for the given record decl which should be used for the vptr at the give...
virtual void setThunkLinkage(cir::FuncOp thunk, bool forVTable, GlobalDecl gd, bool returnAdjustment)=0
Set the linkage and visibility of a thunk function.
virtual mlir::Value performReturnAdjustment(CIRGenFunction &cgf, Address ret, const CXXRecordDecl *unadjustedClass, const ReturnAdjustment &ra)=0
Perform adjustment on a return pointer for a thunk (covariant returns).
virtual llvm::StringRef getPureVirtualCallName()=0
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
Definition CIRGenCall.h:92
void generateThunk(cir::FuncOp fn, const CIRGenFunctionInfo &fnInfo, GlobalDecl gd, const ThunkInfo &thunk, bool isUnprototyped)
Generate code for a thunk function.
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
bool curFuncIsThunk
In C++, whether we are code generating a thunk.
mlir::Value loadCXXThis()
Load the value for 'this'.
const clang::Decl * curFuncDecl
void emitMustTailThunk(GlobalDecl gd, mlir::Value adjustedThisPtr, cir::FuncOp callee)
Emit a musttail call for a thunk with a potentially different ABI.
llvm::ScopedHashTableScope< const clang::Decl *, mlir::Value > SymTableScopeTy
void startThunk(cir::FuncOp fn, GlobalDecl gd, const CIRGenFunctionInfo &fnInfo, bool isUnprototyped)
Start generating a thunk function.
mlir::Type convertTypeForMem(QualType t)
Address returnValue
The temporary alloca to hold the return value.
void emitCallAndReturnForThunk(cir::FuncOp callee, const ThunkInfo *thunk, bool isUnprototyped)
Emit the call and return for a thunk function.
static bool hasAggregateEvaluationKind(clang::QualType type)
void finishFunction(SourceLocation endLoc)
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
const clang::Decl * curCodeDecl
This is the inner-most code context, which includes blocks.
void startFunction(clang::GlobalDecl gd, clang::QualType returnType, cir::FuncOp fn, cir::FuncType funcType, FunctionArgList args, clang::SourceLocation loc, clang::SourceLocation startLoc)
Emit code for the start of a function.
void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param, clang::SourceLocation loc)
We are performing a delegate call; that is, the current function is delegating to another one.
const CIRGenFunctionInfo * curFnInfo
void finishThunk()
Finish generating a thunk function.
This class organizes the cross-function state that is used while generating CIR code.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
CIRGenBuilderTy & getBuilder()
void setDSOLocal(mlir::Operation *op) const
void setGVProperties(mlir::Operation *op, const NamedDecl *d) const
Set visibility, dllimport/dllexport and dso_local.
clang::CharUnits getClassPointerAlignment(const clang::CXXRecordDecl *rd)
Return the best known alignment for an unknown pointer to a particular class.
const clang::TargetInfo & getTarget() const
const llvm::Triple & getTriple() const
static mlir::SymbolTable::Visibility getMLIRVisibility(Visibility v)
cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name, mlir::NamedAttrList extraAttrs={}, bool isLocal=false, bool assumeConvergent=false)
cir::FuncOp getAddrOfThunk(StringRef name, mlir::Type fnTy, GlobalDecl gd)
Get or create a thunk function with the given name and type.
const clang::CodeGenOptions & getCodeGenOpts() const
const clang::LangOptions & getLangOpts() const
cir::FuncOp getOrCreateCIRFunction(llvm::StringRef mangledName, mlir::Type funcType, clang::GlobalDecl gd, bool forVTable, bool dontDefer=false, bool isThunk=false, ForDefinition_t isForDefinition=NotForDefinition, mlir::NamedAttrList extraAttrs={})
CIRGenCXXABI & getCXXABI() const
void setFunctionLinkage(GlobalDecl gd, cir::FuncOp f)
void emitVTable(const CXXRecordDecl *rd)
This is a callback from Sema to tell us that a particular vtable is required to be emitted in this tr...
cir::GlobalLinkageKind getVTableLinkage(const CXXRecordDecl *rd)
Return the appropriate linkage for the vtable, VTT, and type information of the given class.
cir::RecordType getVTableType(const clang::VTableLayout &layout)
Returns the type of a vtable with the given layout.
void createVTableInitializer(cir::GlobalOp &vtable, const clang::VTableLayout &layout, mlir::Attribute rtti, bool vtableHasLocalLinkage)
Add vtable components for the given vtable layout to the given global initializer.
cir::GlobalOp generateConstructionVTable(const CXXRecordDecl *rd, const BaseSubobject &base, bool baseIsVirtual, cir::GlobalLinkageKind linkage, VTableAddressPointsMapTy &addressPoints)
Generate a construction vtable for the given base subobject.
uint64_t getSubVTTIndex(const CXXRecordDecl *rd, BaseSubobject base)
Return the index of the sub-VTT for the base class of the given record decl.
void emitThunks(GlobalDecl gd)
Emit the associated thunks for the given global decl.
void emitVTTDefinition(cir::GlobalOp vttOp, cir::GlobalLinkageKind linkage, const CXXRecordDecl *rd)
Emit the definition of the given vtable.
CIRGenVTables(CIRGenModule &cgm)
cir::FuncOp maybeEmitThunk(GlobalDecl gd, const ThunkInfo &thunkAdjustments, bool forVTable)
Emit a thunk for the given global decl if needed, or return an existing thunk.
void generateClassData(const CXXRecordDecl *rd)
Generate all the class data required to be generated upon definition of a KeyFunction.
cir::GlobalOp getAddrOfVTT(const CXXRecordDecl *rd)
Get the address of the VTT for the given record decl.
clang::ItaniumVTableContext & getItaniumVTableContext()
bool isVTableExternal(const clang::CXXRecordDecl *rd)
At this point in the translation unit, does it appear that can we rely on the vtable being defined el...
uint64_t getSecondaryVirtualPointerIndex(const CXXRecordDecl *rd, BaseSubobject base)
Return the index in the VTT where the virtual pointer for the given subobject is located.
Type for representing both the decl and type of parameters to a function.
Definition CIRGenCall.h:193
This trivial value class is used to represent the result of an expression that is evaluated.
Definition CIRGenValue.h:33
static RValue get(mlir::Value v)
Definition CIRGenValue.h:83
mlir::Value getValue() const
Return the value of this scalar value.
Definition CIRGenValue.h:57
static RequiredArgs getFromProtoWithExtraSlots(const clang::FunctionProtoType *prototype, unsigned additional)
Compute the arguments required by the given formal prototype, given that there may be some additional...
Contains the address where the return value of a function can be stored, and whether the address is v...
Definition CIRGenCall.h:260
Represents a C++ destructor within a class.
Definition DeclCXX.h:2876
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2136
QualType getThisType() const
Return the type of the this pointer.
Definition DeclCXX.cpp:2827
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine whether this particular class is a specialization or instantiation of a class template or m...
Definition DeclCXX.cpp:2060
bool isDynamicClass() const
Definition DeclCXX.h:574
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Definition DeclCXX.h:623
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
bool isZero() const
isZero - Test whether the quantity equals zero.
Definition CharUnits.h:122
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:546
SourceLocation getLocation() const
Definition DeclBase.h:439
bool hasAttr() const
Definition DeclBase.h:577
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
Represents a function declaration or definition.
Definition Decl.h:2000
param_iterator param_end()
Definition Decl.h:2787
bool isInlined() const
Determine whether this function should be inlined, because it is either marked "inline" or "constexpr...
Definition Decl.h:2921
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2774
param_iterator param_begin()
Definition Decl.h:2786
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine what kind of template instantiation this function represents.
Definition Decl.cpp:4418
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3200
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5315
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4511
QualType getReturnType() const
Definition TypeBase.h:4851
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
CXXDtorType getDtorType() const
Definition GlobalDecl.h:113
const Decl * getDecl() const
Definition GlobalDecl.h:106
const VTableLayout & getVTableLayout(const CXXRecordDecl *RD)
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
Definition Mangle.h:52
virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, const ThunkInfo &Thunk, bool ElideOverrideInfo, raw_ostream &)=0
virtual void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, bool ElideOverrideInfo, raw_ostream &)=0
bool isExternallyVisible() const
Definition Decl.h:433
Represents a parameter to a function.
Definition Decl.h:1790
A (possibly-)qualified type.
Definition TypeBase.h:937
Encodes a location in the source.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4894
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
virtual bool emitVectorDeletingDtors(const LangOptions &) const
Controls whether to emit MSVC vector deleting destructors.
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
bool isVoidType() const
Definition TypeBase.h:8991
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9285
bool isReferenceType() const
Definition TypeBase.h:8649
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
Definition Type.cpp:1922
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:753
Class for building VTT layout information.
Definition VTTBuilder.h:71
const llvm::DenseMap< BaseSubobject, uint64_t > & getSecondaryVirtualPointerIndices() const
Returns a reference to the secondary virtual pointer indices.
Definition VTTBuilder.h:157
const llvm::DenseMap< BaseSubobject, uint64_t > & getSubVTTIndices() const
Returns a reference to the sub-VTT indices.
Definition VTTBuilder.h:151
const VTTComponentsVectorTy & getVTTComponents() const
Definition VTTBuilder.h:141
const VTTVTablesVectorTy & getVTTVTables() const
Definition VTTBuilder.h:146
CharUnits getBaseOffset() const
Definition VTTBuilder.h:48
bool isVirtual() const
Definition VTTBuilder.h:52
const CXXRecordDecl * getBase() const
Definition VTTBuilder.h:44
BaseSubobject getBaseSubobject() const
Definition VTTBuilder.h:56
Represents a single component in a vtable.
CharUnits getVBaseOffset() const
Kind getKind() const
Get the kind of this vtable component.
@ CK_DeletingDtorPointer
A pointer to the deleting destructor.
@ CK_UnusedFunctionPointer
An entry that is never used.
@ CK_CompleteDtorPointer
A pointer to the complete destructor.
CharUnits getOffsetToTop() const
GlobalDecl getGlobalDecl(bool HasVectorDeletingDtors) const
CharUnits getVCallOffset() const
SmallVector< ThunkInfo, 1 > ThunkInfoVectorTy
const AddressPointsIndexMapTy & getAddressPointIndices() const
size_t getVTableOffset(size_t i) const
llvm::DenseMap< BaseSubobject, AddressPointLocation > AddressPointsMapTy
AddressPointLocation getAddressPoint(BaseSubobject Base) const
ArrayRef< VTableComponent > vtable_components() const
size_t getNumVTables() const
ArrayRef< VTableThunkTy > vtable_thunks() const
size_t getVTableSize(size_t i) const
QualType getType() const
Definition Decl.h:723
static bool isLocalLinkage(GlobalLinkageKind linkage)
Definition CIROpsEnums.h:51
const AstTypeMatcher< ArrayType > arrayType
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ Dtor_Base
Base object dtor.
Definition ABI.h:37
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
Definition Specifiers.h:188
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
Definition Specifiers.h:206
@ TSK_ExplicitInstantiationDeclaration
This template specialization was instantiated from a template due to an explicit instantiation declar...
Definition Specifiers.h:202
@ TSK_ExplicitSpecialization
This template specialization was declared or defined by an explicit specialization (C++ [temp....
Definition Specifiers.h:198
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
Definition Specifiers.h:194
@ TSK_Undeclared
This template specialization was formed from a template-id but has not yet been declared,...
Definition Specifiers.h:191
U cast(CodeGen::Address addr)
Definition Address.h:327
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
static bool objCLifetime()
static bool opGlobalUnnamedAddr()
static bool vtableEmitMetadata()
static bool setDLLStorageClass()
static bool opCallInAlloca()
static bool pointerAuthentication()
static bool opCallMustTail()
static bool returnValueSlotFeatures()
static bool cudaSupport()
static bool generateDebugInfo()
static bool vtableRelativeLayout()
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
bool isEmpty() const
Definition Thunk.h:70
The this pointer adjustment as well as an optional return adjustment for a thunk.
Definition Thunk.h:157
ReturnAdjustment Return
The return adjustment.
Definition Thunk.h:162
const Type * ThisType
Definition Thunk.h:173