clang 22.0.0git
CIRGenExprConstant.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 to emit Constant Expr nodes as LLVM code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "Address.h"
14#include "CIRGenCXXABI.h"
16#include "CIRGenModule.h"
17#include "CIRGenRecordLayout.h"
18#include "mlir/IR/Attributes.h"
19#include "mlir/IR/BuiltinAttributeInterfaces.h"
20#include "mlir/IR/BuiltinAttributes.h"
21#include "clang/AST/APValue.h"
23#include "clang/AST/Attr.h"
24#include "clang/AST/CharUnits.h"
32#include "llvm/ADT/ArrayRef.h"
33#include "llvm/ADT/STLExtras.h"
34#include "llvm/Support/ErrorHandling.h"
35#include <functional>
36#include <iterator>
37
38using namespace clang;
39using namespace clang::CIRGen;
40
41//===----------------------------------------------------------------------===//
42// ConstantAggregateBuilder
43//===----------------------------------------------------------------------===//
44
45namespace {
46class ConstExprEmitter;
47
48static mlir::TypedAttr computePadding(CIRGenModule &cgm, CharUnits size) {
49 mlir::Type eltTy = cgm.UCharTy;
51 CIRGenBuilderTy &bld = cgm.getBuilder();
52 if (size > CharUnits::One()) {
53 SmallVector<mlir::Attribute> elts(arSize, cir::ZeroAttr::get(eltTy));
54 return bld.getConstArray(mlir::ArrayAttr::get(bld.getContext(), elts),
55 cir::ArrayType::get(eltTy, arSize));
56 }
57
58 return cir::ZeroAttr::get(eltTy);
59}
60
61static mlir::Attribute
62emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
63 mlir::Type commonElementType, unsigned arrayBound,
65 mlir::TypedAttr filler);
66
67struct ConstantAggregateBuilderUtils {
68 CIRGenModule &cgm;
69 cir::CIRDataLayout dataLayout;
70
71 ConstantAggregateBuilderUtils(CIRGenModule &cgm)
72 : cgm(cgm), dataLayout{cgm.getModule()} {}
73
74 CharUnits getAlignment(const mlir::TypedAttr c) const {
76 dataLayout.getAlignment(c.getType(), /*useABIAlign=*/true));
77 }
78
79 CharUnits getSize(mlir::Type ty) const {
80 return CharUnits::fromQuantity(dataLayout.getTypeAllocSize(ty));
81 }
82
83 CharUnits getSize(const mlir::TypedAttr c) const {
84 return getSize(c.getType());
85 }
86
87 mlir::TypedAttr getPadding(CharUnits size) const {
88 return computePadding(cgm, size);
89 }
90};
91
92/// Incremental builder for an mlir::TypedAttr holding a record or array
93/// constant.
94class ConstantAggregateBuilder : private ConstantAggregateBuilderUtils {
95 struct Element {
96 Element(mlir::TypedAttr element, CharUnits offset)
97 : element(element), offset(offset) {}
98
99 mlir::TypedAttr element;
100 /// Describes the offset of `element` within the constant.
101 CharUnits offset;
102 };
103 /// The elements of the constant. The elements are kept in increasing offset
104 /// order, and we ensure that there is no overlap:
105 /// elements.offset[i+1] >= elements.offset[i] + getSize(elements.element[i])
106 ///
107 /// This may contain explicit padding elements (in order to create a
108 /// natural layout), but need not. Gaps between elements are implicitly
109 /// considered to be filled with undef.
110 llvm::SmallVector<Element, 32> elements;
111
112 /// The size of the constant (the maximum end offset of any added element).
113 /// May be larger than the end of elems.back() if we split the last element
114 /// and removed some trailing undefs.
115 CharUnits size = CharUnits::Zero();
116
117 /// This is true only if laying out elems in order as the elements of a
118 /// non-packed LLVM struct will give the correct layout.
119 bool naturalLayout = true;
120
121 static mlir::Attribute buildFrom(CIRGenModule &cgm, ArrayRef<Element> elems,
122 CharUnits startOffset, CharUnits size,
123 bool naturalLayout, mlir::Type desiredTy,
124 bool allowOversized);
125
126public:
127 ConstantAggregateBuilder(CIRGenModule &cgm)
128 : ConstantAggregateBuilderUtils(cgm) {}
129
130 /// Update or overwrite the value starting at \p offset with \c c.
131 ///
132 /// \param allowOverwrite If \c true, this constant might overwrite (part of)
133 /// a constant that has already been added. This flag is only used to
134 /// detect bugs.
135 bool add(mlir::TypedAttr typedAttr, CharUnits offset, bool allowOverwrite);
136
137 /// Update or overwrite the bits starting at \p offsetInBits with \p bits.
138 bool addBits(llvm::APInt bits, uint64_t offsetInBits, bool allowOverwrite);
139
140 /// Produce a constant representing the entire accumulated value, ideally of
141 /// the specified type. If \p allowOversized, the constant might be larger
142 /// than implied by \p desiredTy (eg, if there is a flexible array member).
143 /// Otherwise, the constant will be of exactly the same size as \p desiredTy
144 /// even if we can't represent it as that type.
145 mlir::Attribute build(mlir::Type desiredTy, bool allowOversized) const {
146 return buildFrom(cgm, elements, CharUnits::Zero(), size, naturalLayout,
147 desiredTy, allowOversized);
148 }
149};
150
151template <typename Container, typename Range = std::initializer_list<
152 typename Container::value_type>>
153static void replace(Container &c, size_t beginOff, size_t endOff, Range vals) {
154 assert(beginOff <= endOff && "invalid replacement range");
155 llvm::replace(c, c.begin() + beginOff, c.begin() + endOff, vals);
156}
157
158bool ConstantAggregateBuilder::add(mlir::TypedAttr typedAttr, CharUnits offset,
159 bool allowOverwrite) {
160 // Common case: appending to a layout.
161 if (offset >= size) {
162 CharUnits align = getAlignment(typedAttr);
163 CharUnits alignedSize = size.alignTo(align);
164 if (alignedSize > offset || offset.alignTo(align) != offset) {
165 naturalLayout = false;
166 } else if (alignedSize < offset) {
167 elements.emplace_back(getPadding(offset - size), size);
168 }
169 elements.emplace_back(typedAttr, offset);
170 size = offset + getSize(typedAttr);
171 return true;
172 }
173
174 // Uncommon case: constant overlaps what we've already created.
175 cgm.errorNYI("overlapping constants");
176 return false;
177}
178
179mlir::Attribute
180ConstantAggregateBuilder::buildFrom(CIRGenModule &cgm, ArrayRef<Element> elems,
181 CharUnits startOffset, CharUnits size,
182 bool naturalLayout, mlir::Type desiredTy,
183 bool allowOversized) {
184 ConstantAggregateBuilderUtils utils(cgm);
185
186 if (elems.empty())
187 return cir::UndefAttr::get(desiredTy);
188
189 // If we want an array type, see if all the elements are the same type and
190 // appropriately spaced.
191 if (mlir::isa<cir::ArrayType>(desiredTy)) {
192 cgm.errorNYI("array aggregate constants");
193 return {};
194 }
195
196 // The size of the constant we plan to generate. This is usually just the size
197 // of the initialized type, but in AllowOversized mode (i.e. flexible array
198 // init), it can be larger.
199 CharUnits desiredSize = utils.getSize(desiredTy);
200 if (size > desiredSize) {
201 assert(allowOversized && "elems are oversized");
202 desiredSize = size;
203 }
204
205 // The natural alignment of an unpacked CIR record with the given elements.
206 CharUnits align = CharUnits::One();
207 for (auto [e, offset] : elems)
208 align = std::max(align, utils.getAlignment(e));
209
210 // The natural size of an unpacked LLVM struct with the given elements.
211 CharUnits alignedSize = size.alignTo(align);
212
213 bool packed = false;
214 bool padded = false;
215
216 llvm::SmallVector<mlir::Attribute, 32> unpackedElems;
217 if (desiredSize < alignedSize || desiredSize.alignTo(align) != desiredSize) {
218 naturalLayout = false;
219 packed = true;
220 } else {
221 // The natural layout would be too small. Add padding to fix it. (This
222 // is ignored if we choose a packed layout.)
223 unpackedElems.reserve(elems.size() + 1);
224 llvm::transform(elems, std::back_inserter(unpackedElems),
225 std::mem_fn(&Element::element));
226 if (desiredSize > alignedSize)
227 unpackedElems.push_back(utils.getPadding(desiredSize - size));
228 }
229
230 // If we don't have a natural layout, insert padding as necessary.
231 // As we go, double-check to see if we can actually just emit Elems
232 // as a non-packed record and do so opportunistically if possible.
233 llvm::SmallVector<mlir::Attribute, 32> packedElems;
234 packedElems.reserve(elems.size());
235 if (!naturalLayout) {
236 CharUnits sizeSoFar = CharUnits::Zero();
237 for (auto [element, offset] : elems) {
238 CharUnits align = utils.getAlignment(element);
239 CharUnits naturalOffset = sizeSoFar.alignTo(align);
240 CharUnits desiredOffset = offset - startOffset;
241 assert(desiredOffset >= sizeSoFar && "elements out of order");
242
243 if (desiredOffset != naturalOffset)
244 packed = true;
245 if (desiredOffset != sizeSoFar)
246 packedElems.push_back(utils.getPadding(desiredOffset - sizeSoFar));
247 packedElems.push_back(element);
248 sizeSoFar = desiredOffset + utils.getSize(element);
249 }
250 // If we're using the packed layout, pad it out to the desired size if
251 // necessary.
252 if (packed) {
253 assert(sizeSoFar <= desiredSize &&
254 "requested size is too small for contents");
255
256 if (sizeSoFar < desiredSize)
257 packedElems.push_back(utils.getPadding(desiredSize - sizeSoFar));
258 }
259 }
260
261 CIRGenBuilderTy &builder = cgm.getBuilder();
262 auto arrAttr = mlir::ArrayAttr::get(builder.getContext(),
263 packed ? packedElems : unpackedElems);
264
265 cir::RecordType recordType = builder.getCompleteRecordType(arrAttr, packed);
266 if (auto desired = mlir::dyn_cast<cir::RecordType>(desiredTy))
267 if (desired.isLayoutIdentical(recordType))
268 recordType = desired;
269
270 return builder.getConstRecordOrZeroAttr(arrAttr, packed, padded, recordType);
271}
272
273//===----------------------------------------------------------------------===//
274// ConstRecordBuilder
275//===----------------------------------------------------------------------===//
276
277class ConstRecordBuilder {
278 CIRGenModule &cgm;
279 ConstantEmitter &emitter;
280 ConstantAggregateBuilder &builder;
281 CharUnits startOffset;
282
283public:
284 static mlir::Attribute buildRecord(ConstantEmitter &emitter,
285 InitListExpr *ile, QualType valTy);
286 static mlir::Attribute buildRecord(ConstantEmitter &emitter,
287 const APValue &value, QualType valTy);
288 static bool updateRecord(ConstantEmitter &emitter,
289 ConstantAggregateBuilder &constant, CharUnits offset,
290 InitListExpr *updater);
291
292private:
293 ConstRecordBuilder(ConstantEmitter &emitter,
294 ConstantAggregateBuilder &builder, CharUnits startOffset)
295 : cgm(emitter.cgm), emitter(emitter), builder(builder),
296 startOffset(startOffset) {}
297
298 bool appendField(const FieldDecl *field, uint64_t fieldOffset,
299 mlir::TypedAttr initCst, bool allowOverwrite = false);
300
301 bool appendBytes(CharUnits fieldOffsetInChars, mlir::TypedAttr initCst,
302 bool allowOverwrite = false);
303
304 bool build(InitListExpr *ile, bool allowOverwrite);
305 bool build(const APValue &val, const RecordDecl *rd, bool isPrimaryBase,
306 const CXXRecordDecl *vTableClass, CharUnits baseOffset);
307
308 mlir::Attribute finalize(QualType ty);
309};
310
311bool ConstRecordBuilder::appendField(const FieldDecl *field,
312 uint64_t fieldOffset,
313 mlir::TypedAttr initCst,
314 bool allowOverwrite) {
315 const ASTContext &astContext = cgm.getASTContext();
316
317 CharUnits fieldOffsetInChars = astContext.toCharUnitsFromBits(fieldOffset);
318
319 return appendBytes(fieldOffsetInChars, initCst, allowOverwrite);
320}
321
322bool ConstRecordBuilder::appendBytes(CharUnits fieldOffsetInChars,
323 mlir::TypedAttr initCst,
324 bool allowOverwrite) {
325 return builder.add(initCst, startOffset + fieldOffsetInChars, allowOverwrite);
326}
327
328bool ConstRecordBuilder::build(InitListExpr *ile, bool allowOverwrite) {
329 RecordDecl *rd = ile->getType()
330 ->castAs<clang::RecordType>()
331 ->getOriginalDecl()
332 ->getDefinitionOrSelf();
333 const ASTRecordLayout &layout = cgm.getASTContext().getASTRecordLayout(rd);
334
335 // Bail out if we have base classes. We could support these, but they only
336 // arise in C++1z where we will have already constant folded most interesting
337 // cases. FIXME: There are still a few more cases we can handle this way.
338 if (auto *cxxrd = dyn_cast<CXXRecordDecl>(rd))
339 if (cxxrd->getNumBases())
340 return false;
341
342 if (cgm.shouldZeroInitPadding()) {
344 cgm.errorNYI(rd->getSourceRange(), "zero init padding");
345 return false;
346 }
347
348 unsigned elementNo = 0;
349 for (auto [index, field] : llvm::enumerate(rd->fields())) {
350
351 // If this is a union, skip all the fields that aren't being initialized.
352 if (rd->isUnion() &&
354 continue;
355
356 // Don't emit anonymous bitfields.
357 if (field->isUnnamedBitField())
358 continue;
359
360 // Get the initializer. A record can include fields without initializers,
361 // we just use explicit null values for them.
362 Expr *init = nullptr;
363 if (elementNo < ile->getNumInits())
364 init = ile->getInit(elementNo++);
365 if (isa_and_nonnull<NoInitExpr>(init))
366 continue;
367
368 // Zero-sized fields are not emitted, but their initializers may still
369 // prevent emission of this record as a constant.
370 if (field->isZeroSize(cgm.getASTContext())) {
371 if (init->HasSideEffects(cgm.getASTContext()))
372 return false;
373 continue;
374 }
375
377
378 // When emitting a DesignatedInitUpdateExpr, a nested InitListExpr
379 // represents additional overwriting of our current constant value, and not
380 // a new constant to emit independently.
381 if (allowOverwrite &&
382 (field->getType()->isArrayType() || field->getType()->isRecordType())) {
383 cgm.errorNYI(field->getSourceRange(), "designated init lists");
384 return false;
385 }
386
387 mlir::TypedAttr eltInit;
388 if (init)
389 eltInit = mlir::cast<mlir::TypedAttr>(
390 emitter.tryEmitPrivateForMemory(init, field->getType()));
391 else
392 eltInit = mlir::cast<mlir::TypedAttr>(emitter.emitNullForMemory(
393 cgm.getLoc(ile->getSourceRange()), field->getType()));
394
395 if (!eltInit)
396 return false;
397
398 if (!field->isBitField()) {
399 // Handle non-bitfield members.
400 if (!appendField(field, layout.getFieldOffset(index), eltInit,
401 allowOverwrite))
402 return false;
403 // After emitting a non-empty field with [[no_unique_address]], we may
404 // need to overwrite its tail padding.
405 if (field->hasAttr<NoUniqueAddressAttr>())
406 allowOverwrite = true;
407 } else {
408 // Otherwise we have a bitfield.
409 if (auto constInt = dyn_cast<cir::IntAttr>(eltInit)) {
411 cgm.errorNYI(field->getSourceRange(), "bitfields");
412 }
413 // We are trying to initialize a bitfield with a non-trivial constant,
414 // this must require run-time code.
415 return false;
416 }
417 }
418
420 return true;
421}
422
423namespace {
424struct BaseInfo {
425 BaseInfo(const CXXRecordDecl *decl, CharUnits offset, unsigned index)
426 : decl(decl), offset(offset), index(index) {}
427
428 const CXXRecordDecl *decl;
429 CharUnits offset;
430 unsigned index;
431
432 bool operator<(const BaseInfo &o) const { return offset < o.offset; }
433};
434} // namespace
435
436bool ConstRecordBuilder::build(const APValue &val, const RecordDecl *rd,
437 bool isPrimaryBase,
438 const CXXRecordDecl *vTableClass,
439 CharUnits offset) {
440 const ASTRecordLayout &layout = cgm.getASTContext().getASTRecordLayout(rd);
441 if (const CXXRecordDecl *cd = dyn_cast<CXXRecordDecl>(rd)) {
442 // Add a vtable pointer, if we need one and it hasn't already been added.
443 if (layout.hasOwnVFPtr()) {
444 CIRGenBuilderTy &builder = cgm.getBuilder();
445 cir::GlobalOp vtable =
446 cgm.getCXXABI().getAddrOfVTable(vTableClass, CharUnits());
447 clang::VTableLayout::AddressPointLocation addressPoint =
449 .getVTableLayout(vTableClass)
450 .getAddressPoint(BaseSubobject(cd, offset));
452 mlir::ArrayAttr indices = builder.getArrayAttr({
453 builder.getI32IntegerAttr(addressPoint.VTableIndex),
454 builder.getI32IntegerAttr(addressPoint.AddressPointIndex),
455 });
456 cir::GlobalViewAttr vtableInit =
457 cgm.getBuilder().getGlobalViewAttr(vtable, indices);
458 if (!appendBytes(offset, vtableInit))
459 return false;
460 }
461
462 // Accumulate and sort bases, in order to visit them in address order, which
463 // may not be the same as declaration order.
464 SmallVector<BaseInfo> bases;
465 bases.reserve(cd->getNumBases());
466 for (auto [index, base] : llvm::enumerate(cd->bases())) {
467 assert(!base.isVirtual() && "should not have virtual bases here");
468 const CXXRecordDecl *bd = base.getType()->getAsCXXRecordDecl();
469 CharUnits baseOffset = layout.getBaseClassOffset(bd);
470 bases.push_back(BaseInfo(bd, baseOffset, index));
471 }
472#ifdef EXPENSIVE_CHECKS
473 assert(llvm::is_sorted(bases) && "bases not sorted by offset");
474#endif
475
476 for (BaseInfo &base : bases) {
477 bool isPrimaryBase = layout.getPrimaryBase() == base.decl;
478 build(val.getStructBase(base.index), base.decl, isPrimaryBase,
479 vTableClass, offset + base.offset);
480 }
481 }
482
483 uint64_t offsetBits = cgm.getASTContext().toBits(offset);
484
485 bool allowOverwrite = false;
486 for (auto [index, field] : llvm::enumerate(rd->fields())) {
487 // If this is a union, skip all the fields that aren't being initialized.
488 if (rd->isUnion() && !declaresSameEntity(val.getUnionField(), field))
489 continue;
490
491 // Don't emit anonymous bitfields or zero-sized fields.
492 if (field->isUnnamedBitField() || field->isZeroSize(cgm.getASTContext()))
493 continue;
494
495 // Emit the value of the initializer.
496 const APValue &fieldValue =
497 rd->isUnion() ? val.getUnionValue() : val.getStructField(index);
498 mlir::TypedAttr eltInit = mlir::cast<mlir::TypedAttr>(
499 emitter.tryEmitPrivateForMemory(fieldValue, field->getType()));
500 if (!eltInit)
501 return false;
502
503 if (!field->isBitField()) {
504 // Handle non-bitfield members.
505 if (!appendField(field, layout.getFieldOffset(index) + offsetBits,
506 eltInit, allowOverwrite))
507 return false;
508 // After emitting a non-empty field with [[no_unique_address]], we may
509 // need to overwrite its tail padding.
510 if (field->hasAttr<NoUniqueAddressAttr>())
511 allowOverwrite = true;
512 } else {
514 cgm.errorNYI(field->getSourceRange(), "bitfields");
515 }
516 }
517
518 return true;
519}
520
521mlir::Attribute ConstRecordBuilder::finalize(QualType type) {
522 type = type.getNonReferenceType();
523 RecordDecl *rd = type->castAs<clang::RecordType>()
524 ->getOriginalDecl()
526 mlir::Type valTy = cgm.convertType(type);
527 return builder.build(valTy, rd->hasFlexibleArrayMember());
528}
529
530mlir::Attribute ConstRecordBuilder::buildRecord(ConstantEmitter &emitter,
531 InitListExpr *ile,
532 QualType valTy) {
533 ConstantAggregateBuilder constant(emitter.cgm);
534 ConstRecordBuilder builder(emitter, constant, CharUnits::Zero());
535
536 if (!builder.build(ile, /*allowOverwrite*/ false))
537 return nullptr;
538
539 return builder.finalize(valTy);
540}
541
542mlir::Attribute ConstRecordBuilder::buildRecord(ConstantEmitter &emitter,
543 const APValue &val,
544 QualType valTy) {
545 ConstantAggregateBuilder constant(emitter.cgm);
546 ConstRecordBuilder builder(emitter, constant, CharUnits::Zero());
547
548 const RecordDecl *rd = valTy->castAs<clang::RecordType>()
549 ->getOriginalDecl()
550 ->getDefinitionOrSelf();
551 const CXXRecordDecl *cd = dyn_cast<CXXRecordDecl>(rd);
552 if (!builder.build(val, rd, false, cd, CharUnits::Zero()))
553 return nullptr;
554
555 return builder.finalize(valTy);
556}
557
558bool ConstRecordBuilder::updateRecord(ConstantEmitter &emitter,
559 ConstantAggregateBuilder &constant,
560 CharUnits offset, InitListExpr *updater) {
561 return ConstRecordBuilder(emitter, constant, offset)
562 .build(updater, /*allowOverwrite*/ true);
563}
564
565//===----------------------------------------------------------------------===//
566// ConstExprEmitter
567//===----------------------------------------------------------------------===//
568
569// This class only needs to handle arrays, structs and unions.
570//
571// In LLVM codegen, when outside C++11 mode, those types are not constant
572// folded, while all other types are handled by constant folding.
573//
574// In CIR codegen, instead of folding things here, we should defer that work
575// to MLIR: do not attempt to do much here.
576class ConstExprEmitter
577 : public StmtVisitor<ConstExprEmitter, mlir::Attribute, QualType> {
578 CIRGenModule &cgm;
579 LLVM_ATTRIBUTE_UNUSED ConstantEmitter &emitter;
580
581public:
582 ConstExprEmitter(ConstantEmitter &emitter)
583 : cgm(emitter.cgm), emitter(emitter) {}
584
585 //===--------------------------------------------------------------------===//
586 // Visitor Methods
587 //===--------------------------------------------------------------------===//
588
589 mlir::Attribute VisitStmt(Stmt *s, QualType t) { return {}; }
590
591 mlir::Attribute VisitConstantExpr(ConstantExpr *ce, QualType t) {
592 if (mlir::Attribute result = emitter.tryEmitConstantExpr(ce))
593 return result;
594 return Visit(ce->getSubExpr(), t);
595 }
596
597 mlir::Attribute VisitParenExpr(ParenExpr *pe, QualType t) {
598 return Visit(pe->getSubExpr(), t);
599 }
600
601 mlir::Attribute
602 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe,
603 QualType t) {
604 return Visit(pe->getReplacement(), t);
605 }
606
607 mlir::Attribute VisitGenericSelectionExpr(GenericSelectionExpr *ge,
608 QualType t) {
609 return Visit(ge->getResultExpr(), t);
610 }
611
612 mlir::Attribute VisitChooseExpr(ChooseExpr *ce, QualType t) {
613 return Visit(ce->getChosenSubExpr(), t);
614 }
615
616 mlir::Attribute VisitCompoundLiteralExpr(CompoundLiteralExpr *e, QualType t) {
617 return Visit(e->getInitializer(), t);
618 }
619
620 mlir::Attribute VisitCastExpr(CastExpr *e, QualType destType) {
622 cgm.errorNYI(e->getBeginLoc(),
623 "ConstExprEmitter::VisitCastExpr explicit cast");
624
625 Expr *subExpr = e->getSubExpr();
626
627 switch (e->getCastKind()) {
628 case CK_ToUnion:
629 case CK_AddressSpaceConversion:
630 case CK_ReinterpretMemberPointer:
631 case CK_DerivedToBaseMemberPointer:
632 case CK_BaseToDerivedMemberPointer:
633 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitCastExpr");
634 return {};
635
636 case CK_LValueToRValue:
637 case CK_AtomicToNonAtomic:
638 case CK_NonAtomicToAtomic:
639 case CK_NoOp:
640 case CK_ConstructorConversion:
641 return Visit(subExpr, destType);
642
643 case CK_IntToOCLSampler:
644 llvm_unreachable("global sampler variables are not generated");
645
646 case CK_Dependent:
647 llvm_unreachable("saw dependent cast!");
648
649 case CK_BuiltinFnToFnPtr:
650 llvm_unreachable("builtin functions are handled elsewhere");
651
652 // These will never be supported.
653 case CK_ObjCObjectLValueCast:
654 case CK_ARCProduceObject:
655 case CK_ARCConsumeObject:
656 case CK_ARCReclaimReturnedObject:
657 case CK_ARCExtendBlockObject:
658 case CK_CopyAndAutoreleaseBlockObject:
659 return {};
660
661 // These don't need to be handled here because Evaluate knows how to
662 // evaluate them in the cases where they can be folded.
663 case CK_BitCast:
664 case CK_ToVoid:
665 case CK_Dynamic:
666 case CK_LValueBitCast:
667 case CK_LValueToRValueBitCast:
668 case CK_NullToMemberPointer:
669 case CK_UserDefinedConversion:
670 case CK_CPointerToObjCPointerCast:
671 case CK_BlockPointerToObjCPointerCast:
672 case CK_AnyPointerToBlockPointerCast:
673 case CK_ArrayToPointerDecay:
674 case CK_FunctionToPointerDecay:
675 case CK_BaseToDerived:
676 case CK_DerivedToBase:
677 case CK_UncheckedDerivedToBase:
678 case CK_MemberPointerToBoolean:
679 case CK_VectorSplat:
680 case CK_FloatingRealToComplex:
681 case CK_FloatingComplexToReal:
682 case CK_FloatingComplexToBoolean:
683 case CK_FloatingComplexCast:
684 case CK_FloatingComplexToIntegralComplex:
685 case CK_IntegralRealToComplex:
686 case CK_IntegralComplexToReal:
687 case CK_IntegralComplexToBoolean:
688 case CK_IntegralComplexCast:
689 case CK_IntegralComplexToFloatingComplex:
690 case CK_PointerToIntegral:
691 case CK_PointerToBoolean:
692 case CK_NullToPointer:
693 case CK_IntegralCast:
694 case CK_BooleanToSignedIntegral:
695 case CK_IntegralToPointer:
696 case CK_IntegralToBoolean:
697 case CK_IntegralToFloating:
698 case CK_FloatingToIntegral:
699 case CK_FloatingToBoolean:
700 case CK_FloatingCast:
701 case CK_FloatingToFixedPoint:
702 case CK_FixedPointToFloating:
703 case CK_FixedPointCast:
704 case CK_FixedPointToBoolean:
705 case CK_FixedPointToIntegral:
706 case CK_IntegralToFixedPoint:
707 case CK_ZeroToOCLOpaqueType:
708 case CK_MatrixCast:
709 case CK_HLSLArrayRValue:
710 case CK_HLSLVectorTruncation:
711 case CK_HLSLElementwiseCast:
712 case CK_HLSLAggregateSplatCast:
713 return {};
714 }
715 llvm_unreachable("Invalid CastKind");
716 }
717
718 mlir::Attribute VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die, QualType t) {
719 cgm.errorNYI(die->getBeginLoc(),
720 "ConstExprEmitter::VisitCXXDefaultInitExpr");
721 return {};
722 }
723
724 mlir::Attribute VisitExprWithCleanups(ExprWithCleanups *e, QualType t) {
725 // Since this about constant emission no need to wrap this under a scope.
726 return Visit(e->getSubExpr(), t);
727 }
728
729 mlir::Attribute VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e,
730 QualType t) {
731 return Visit(e->getSubExpr(), t);
732 }
733
734 mlir::Attribute VisitImplicitValueInitExpr(ImplicitValueInitExpr *e,
735 QualType t) {
736 cgm.errorNYI(e->getBeginLoc(),
737 "ConstExprEmitter::VisitImplicitValueInitExpr");
738 return {};
739 }
740
741 mlir::Attribute VisitInitListExpr(InitListExpr *ile, QualType t) {
742 if (ile->isTransparent())
743 return Visit(ile->getInit(0), t);
744
745 if (ile->getType()->isArrayType()) {
746 // If we return null here, the non-constant initializer will take care of
747 // it, but we would prefer to handle it here.
749 return {};
750 }
751
752 if (ile->getType()->isRecordType()) {
753 return ConstRecordBuilder::buildRecord(emitter, ile, t);
754 }
755
756 if (ile->getType()->isVectorType()) {
757 // If we return null here, the non-constant initializer will take care of
758 // it, but we would prefer to handle it here.
760 return {};
761 }
762
763 return {};
764 }
765
766 mlir::Attribute VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e,
767 QualType destType) {
768 mlir::Attribute c = Visit(e->getBase(), destType);
769 if (!c)
770 return {};
771
772 cgm.errorNYI(e->getBeginLoc(),
773 "ConstExprEmitter::VisitDesignatedInitUpdateExpr");
774 return {};
775 }
776
777 mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {
778 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitCXXConstructExpr");
779 return {};
780 }
781
782 mlir::Attribute VisitStringLiteral(StringLiteral *e, QualType t) {
783 // This is a string literal initializing an array in an initializer.
785 }
786
787 mlir::Attribute VisitObjCEncodeExpr(ObjCEncodeExpr *e, QualType t) {
788 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitObjCEncodeExpr");
789 return {};
790 }
791
792 mlir::Attribute VisitUnaryExtension(const UnaryOperator *e, QualType t) {
793 return Visit(e->getSubExpr(), t);
794 }
795
796 // Utility methods
797 mlir::Type convertType(QualType t) { return cgm.convertType(t); }
798};
799
800// TODO(cir): this can be shared with LLVM's codegen
801static QualType getNonMemoryType(CIRGenModule &cgm, QualType type) {
802 if (const auto *at = type->getAs<AtomicType>()) {
803 return cgm.getASTContext().getQualifiedType(at->getValueType(),
804 type.getQualifiers());
805 }
806 return type;
807}
808
809static mlir::Attribute
810emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
811 mlir::Type commonElementType, unsigned arrayBound,
812 SmallVectorImpl<mlir::TypedAttr> &elements,
813 mlir::TypedAttr filler) {
814 CIRGenBuilderTy &builder = cgm.getBuilder();
815
816 unsigned nonzeroLength = arrayBound;
817 if (elements.size() < nonzeroLength && builder.isNullValue(filler))
818 nonzeroLength = elements.size();
819
820 if (nonzeroLength == elements.size()) {
821 while (nonzeroLength > 0 &&
822 builder.isNullValue(elements[nonzeroLength - 1]))
823 --nonzeroLength;
824 }
825
826 if (nonzeroLength == 0)
827 return cir::ZeroAttr::get(desiredType);
828
829 const unsigned trailingZeroes = arrayBound - nonzeroLength;
830
831 // Add a zeroinitializer array filler if we have lots of trailing zeroes.
832 if (trailingZeroes >= 8) {
833 assert(elements.size() >= nonzeroLength &&
834 "missing initializer for non-zero element");
835
836 if (commonElementType && nonzeroLength >= 8) {
837 // If all the elements had the same type up to the trailing zeroes and
838 // there are eight or more nonzero elements, emit a struct of two arrays
839 // (the nonzero data and the zeroinitializer).
840 SmallVector<mlir::Attribute> eles;
841 eles.reserve(nonzeroLength);
842 for (const auto &element : elements)
843 eles.push_back(element);
844 auto initial = cir::ConstArrayAttr::get(
845 cir::ArrayType::get(commonElementType, nonzeroLength),
846 mlir::ArrayAttr::get(builder.getContext(), eles));
847 elements.resize(2);
848 elements[0] = initial;
849 } else {
850 // Otherwise, emit a struct with individual elements for each nonzero
851 // initializer, followed by a zeroinitializer array filler.
852 elements.resize(nonzeroLength + 1);
853 }
854
855 mlir::Type fillerType =
856 commonElementType
857 ? commonElementType
858 : mlir::cast<cir::ArrayType>(desiredType).getElementType();
859 fillerType = cir::ArrayType::get(fillerType, trailingZeroes);
860 elements.back() = cir::ZeroAttr::get(fillerType);
861 commonElementType = nullptr;
862 } else if (elements.size() != arrayBound) {
863 elements.resize(arrayBound, filler);
864
865 if (filler.getType() != commonElementType)
866 commonElementType = {};
867 }
868
869 if (commonElementType) {
870 SmallVector<mlir::Attribute> eles;
871 eles.reserve(elements.size());
872
873 for (const auto &element : elements)
874 eles.push_back(element);
875
876 return cir::ConstArrayAttr::get(
877 cir::ArrayType::get(commonElementType, arrayBound),
878 mlir::ArrayAttr::get(builder.getContext(), eles));
879 }
880
881 SmallVector<mlir::Attribute> eles;
882 eles.reserve(elements.size());
883 for (auto const &element : elements)
884 eles.push_back(element);
885
886 auto arrAttr = mlir::ArrayAttr::get(builder.getContext(), eles);
887 return builder.getAnonConstRecord(arrAttr, /*packed=*/true);
888}
889
890} // namespace
891
892//===----------------------------------------------------------------------===//
893// ConstantLValueEmitter
894//===----------------------------------------------------------------------===//
895
896namespace {
897/// A struct which can be used to peephole certain kinds of finalization
898/// that normally happen during l-value emission.
899struct ConstantLValue {
900 llvm::PointerUnion<mlir::Value, mlir::Attribute> value;
901 bool hasOffsetApplied;
902
903 /*implicit*/ ConstantLValue(std::nullptr_t)
904 : value(nullptr), hasOffsetApplied(false) {}
905 /*implicit*/ ConstantLValue(cir::GlobalViewAttr address)
906 : value(address), hasOffsetApplied(false) {}
907
908 ConstantLValue() : value(nullptr), hasOffsetApplied(false) {}
909};
910
911/// A helper class for emitting constant l-values.
912class ConstantLValueEmitter
913 : public ConstStmtVisitor<ConstantLValueEmitter, ConstantLValue> {
914 CIRGenModule &cgm;
915 ConstantEmitter &emitter;
916 const APValue &value;
917 QualType destType;
918
919 // Befriend StmtVisitorBase so that we don't have to expose Visit*.
920 friend StmtVisitorBase;
921
922public:
923 ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value,
924 QualType destType)
925 : cgm(emitter.cgm), emitter(emitter), value(value), destType(destType) {}
926
927 mlir::Attribute tryEmit();
928
929private:
930 mlir::Attribute tryEmitAbsolute(mlir::Type destTy);
931 ConstantLValue tryEmitBase(const APValue::LValueBase &base);
932
933 ConstantLValue VisitStmt(const Stmt *s) { return nullptr; }
934 ConstantLValue VisitConstantExpr(const ConstantExpr *e);
935 ConstantLValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *e);
936 ConstantLValue VisitStringLiteral(const StringLiteral *e);
937 ConstantLValue VisitObjCBoxedExpr(const ObjCBoxedExpr *e);
938 ConstantLValue VisitObjCEncodeExpr(const ObjCEncodeExpr *e);
939 ConstantLValue VisitObjCStringLiteral(const ObjCStringLiteral *e);
940 ConstantLValue VisitPredefinedExpr(const PredefinedExpr *e);
941 ConstantLValue VisitAddrLabelExpr(const AddrLabelExpr *e);
942 ConstantLValue VisitCallExpr(const CallExpr *e);
943 ConstantLValue VisitBlockExpr(const BlockExpr *e);
944 ConstantLValue VisitCXXTypeidExpr(const CXXTypeidExpr *e);
945 ConstantLValue
946 VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e);
947
948 /// Return GEP-like value offset
949 mlir::ArrayAttr getOffset(mlir::Type ty) {
950 int64_t offset = value.getLValueOffset().getQuantity();
951 cir::CIRDataLayout layout(cgm.getModule());
952 SmallVector<int64_t, 3> idxVec;
953 cgm.getBuilder().computeGlobalViewIndicesFromFlatOffset(offset, ty, layout,
954 idxVec);
955
956 llvm::SmallVector<mlir::Attribute, 3> indices;
957 for (int64_t i : idxVec) {
958 mlir::IntegerAttr intAttr = cgm.getBuilder().getI32IntegerAttr(i);
959 indices.push_back(intAttr);
960 }
961
962 if (indices.empty())
963 return {};
964 return cgm.getBuilder().getArrayAttr(indices);
965 }
966
967 /// Apply the value offset to the given constant.
968 ConstantLValue applyOffset(ConstantLValue &c) {
969 // Handle attribute constant LValues.
970 if (auto attr = mlir::dyn_cast<mlir::Attribute>(c.value)) {
971 if (auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(attr)) {
972 auto baseTy = mlir::cast<cir::PointerType>(gv.getType()).getPointee();
973 mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
974 assert(!gv.getIndices() && "Global view is already indexed");
975 return cir::GlobalViewAttr::get(destTy, gv.getSymbol(),
976 getOffset(baseTy));
977 }
978 llvm_unreachable("Unsupported attribute type to offset");
979 }
980
981 cgm.errorNYI("ConstantLValue: non-attribute offset");
982 return {};
983 }
984};
985
986} // namespace
987
988mlir::Attribute ConstantLValueEmitter::tryEmit() {
989 const APValue::LValueBase &base = value.getLValueBase();
990
991 // The destination type should be a pointer or reference
992 // type, but it might also be a cast thereof.
993 //
994 // FIXME: the chain of casts required should be reflected in the APValue.
995 // We need this in order to correctly handle things like a ptrtoint of a
996 // non-zero null pointer and addrspace casts that aren't trivially
997 // represented in LLVM IR.
998 mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
999 assert(mlir::isa<cir::PointerType>(destTy));
1000
1001 // If there's no base at all, this is a null or absolute pointer,
1002 // possibly cast back to an integer type.
1003 if (!base)
1004 return tryEmitAbsolute(destTy);
1005
1006 // Otherwise, try to emit the base.
1007 ConstantLValue result = tryEmitBase(base);
1008
1009 // If that failed, we're done.
1010 llvm::PointerUnion<mlir::Value, mlir::Attribute> &value = result.value;
1011 if (!value)
1012 return {};
1013
1014 // Apply the offset if necessary and not already done.
1015 if (!result.hasOffsetApplied)
1016 value = applyOffset(result).value;
1017
1018 // Convert to the appropriate type; this could be an lvalue for
1019 // an integer. FIXME: performAddrSpaceCast
1020 if (mlir::isa<cir::PointerType>(destTy)) {
1021 if (auto attr = mlir::dyn_cast<mlir::Attribute>(value))
1022 return attr;
1023 cgm.errorNYI("ConstantLValueEmitter: non-attribute pointer");
1024 return {};
1025 }
1026
1027 cgm.errorNYI("ConstantLValueEmitter: other?");
1028 return {};
1029}
1030
1031/// Try to emit an absolute l-value, such as a null pointer or an integer
1032/// bitcast to pointer type.
1033mlir::Attribute ConstantLValueEmitter::tryEmitAbsolute(mlir::Type destTy) {
1034 // If we're producing a pointer, this is easy.
1035 auto destPtrTy = mlir::cast<cir::PointerType>(destTy);
1036 return cgm.getBuilder().getConstPtrAttr(
1037 destPtrTy, value.getLValueOffset().getQuantity());
1038}
1039
1040ConstantLValue
1041ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
1042 // Handle values.
1043 if (const ValueDecl *d = base.dyn_cast<const ValueDecl *>()) {
1044 // The constant always points to the canonical declaration. We want to look
1045 // at properties of the most recent declaration at the point of emission.
1046 d = cast<ValueDecl>(d->getMostRecentDecl());
1047
1048 if (d->hasAttr<WeakRefAttr>()) {
1049 cgm.errorNYI(d->getSourceRange(),
1050 "ConstantLValueEmitter: emit pointer base for weakref");
1051 return {};
1052 }
1053
1054 if (auto *fd = dyn_cast<FunctionDecl>(d)) {
1055 cir::FuncOp fop = cgm.getAddrOfFunction(fd);
1056 CIRGenBuilderTy &builder = cgm.getBuilder();
1057 mlir::MLIRContext *mlirContext = builder.getContext();
1058 return cir::GlobalViewAttr::get(
1059 builder.getPointerTo(fop.getFunctionType()),
1060 mlir::FlatSymbolRefAttr::get(mlirContext, fop.getSymNameAttr()));
1061 }
1062
1063 if (auto *vd = dyn_cast<VarDecl>(d)) {
1064 // We can never refer to a variable with local storage.
1065 if (!vd->hasLocalStorage()) {
1066 if (vd->isFileVarDecl() || vd->hasExternalStorage())
1067 return cgm.getAddrOfGlobalVarAttr(vd);
1068
1069 if (vd->isLocalVarDecl()) {
1070 cgm.errorNYI(vd->getSourceRange(),
1071 "ConstantLValueEmitter: local var decl");
1072 return {};
1073 }
1074 }
1075 }
1076
1077 // Classic codegen handles MSGuidDecl,UnnamedGlobalConstantDecl, and
1078 // TemplateParamObjectDecl, but it can also fall through from VarDecl,
1079 // in which case it silently returns nullptr. For now, let's emit an
1080 // error to see what cases we need to handle.
1081 cgm.errorNYI(d->getSourceRange(),
1082 "ConstantLValueEmitter: unhandled value decl");
1083 return {};
1084 }
1085
1086 // Handle typeid(T).
1087 if (base.dyn_cast<TypeInfoLValue>()) {
1088 cgm.errorNYI("ConstantLValueEmitter: typeid");
1089 return {};
1090 }
1091
1092 // Otherwise, it must be an expression.
1093 return Visit(base.get<const Expr *>());
1094}
1095
1096ConstantLValue ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *e) {
1097 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: constant expr");
1098 return {};
1099}
1100
1101ConstantLValue
1102ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *e) {
1103 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: compound literal");
1104 return {};
1105}
1106
1107ConstantLValue
1108ConstantLValueEmitter::VisitStringLiteral(const StringLiteral *e) {
1110}
1111
1112ConstantLValue
1113ConstantLValueEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *e) {
1114 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: objc encode expr");
1115 return {};
1116}
1117
1118ConstantLValue
1119ConstantLValueEmitter::VisitObjCStringLiteral(const ObjCStringLiteral *e) {
1120 cgm.errorNYI(e->getSourceRange(),
1121 "ConstantLValueEmitter: objc string literal");
1122 return {};
1123}
1124
1125ConstantLValue
1126ConstantLValueEmitter::VisitObjCBoxedExpr(const ObjCBoxedExpr *e) {
1127 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: objc boxed expr");
1128 return {};
1129}
1130
1131ConstantLValue
1132ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *e) {
1133 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: predefined expr");
1134 return {};
1135}
1136
1137ConstantLValue
1138ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *e) {
1139 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: addr label expr");
1140 return {};
1141}
1142
1143ConstantLValue ConstantLValueEmitter::VisitCallExpr(const CallExpr *e) {
1144 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: call expr");
1145 return {};
1146}
1147
1148ConstantLValue ConstantLValueEmitter::VisitBlockExpr(const BlockExpr *e) {
1149 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: block expr");
1150 return {};
1151}
1152
1153ConstantLValue
1154ConstantLValueEmitter::VisitCXXTypeidExpr(const CXXTypeidExpr *e) {
1155 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: cxx typeid expr");
1156 return {};
1157}
1158
1159ConstantLValue ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
1160 const MaterializeTemporaryExpr *e) {
1161 cgm.errorNYI(e->getSourceRange(),
1162 "ConstantLValueEmitter: materialize temporary expr");
1163 return {};
1164}
1165
1166//===----------------------------------------------------------------------===//
1167// ConstantEmitter
1168//===----------------------------------------------------------------------===//
1169
1171 initializeNonAbstract();
1172 return markIfFailed(tryEmitPrivateForVarInit(d));
1173}
1174
1175void ConstantEmitter::finalize(cir::GlobalOp gv) {
1176 assert(initializedNonAbstract &&
1177 "finalizing emitter that was used for abstract emission?");
1178 assert(!finalized && "finalizing emitter multiple times");
1179 assert(!gv.isDeclaration());
1180#ifndef NDEBUG
1181 // Note that we might also be Failed.
1182 finalized = true;
1183#endif // NDEBUG
1184}
1185
1186mlir::Attribute
1188 AbstractStateRAII state(*this, true);
1189 return tryEmitPrivateForVarInit(d);
1190}
1191
1193 assert((!initializedNonAbstract || finalized || failed) &&
1194 "not finalized after being initialized for non-abstract emission");
1195}
1196
1198 // Make a quick check if variable can be default NULL initialized
1199 // and avoid going through rest of code which may do, for c++11,
1200 // initialization of memory to all NULLs.
1201 if (!d.hasLocalStorage()) {
1202 QualType ty = cgm.getASTContext().getBaseElementType(d.getType());
1203 if (ty->isRecordType()) {
1204 if (const auto *e = dyn_cast_or_null<CXXConstructExpr>(d.getInit())) {
1205 const CXXConstructorDecl *cd = e->getConstructor();
1206 // FIXME: we should probably model this more closely to C++ than
1207 // just emitting a global with zero init (mimic what we do for trivial
1208 // assignments and whatnots). Since this is for globals shouldn't
1209 // be a problem for the near future.
1210 if (cd->isTrivial() && cd->isDefaultConstructor()) {
1211 const auto *cxxrd = ty->castAsCXXRecordDecl();
1212 if (cxxrd->getNumBases() != 0) {
1213 // There may not be anything additional to do here, but this will
1214 // force us to pause and test this path when it is supported.
1215 cgm.errorNYI("tryEmitPrivateForVarInit: cxx record with bases");
1216 return {};
1217 }
1218 if (!cgm.getTypes().isZeroInitializable(cxxrd)) {
1219 // To handle this case, we really need to go through
1220 // emitNullConstant, but we need an attribute, not a value
1221 cgm.errorNYI(
1222 "tryEmitPrivateForVarInit: non-zero-initializable cxx record");
1223 return {};
1224 }
1225 return cir::ZeroAttr::get(cgm.convertType(d.getType()));
1226 }
1227 }
1228 }
1229 }
1230 inConstantContext = d.hasConstantInitialization();
1231
1232 const Expr *e = d.getInit();
1233 assert(e && "No initializer to emit");
1234
1235 QualType destType = d.getType();
1236
1237 if (!destType->isReferenceType()) {
1238 QualType nonMemoryDestType = getNonMemoryType(cgm, destType);
1239 if (mlir::Attribute c = ConstExprEmitter(*this).Visit(const_cast<Expr *>(e),
1240 nonMemoryDestType))
1241 return emitForMemory(c, destType);
1242 }
1243
1244 // Try to emit the initializer. Note that this can allow some things that
1245 // are not allowed by tryEmitPrivateForMemory alone.
1246 if (APValue *value = d.evaluateValue())
1247 return tryEmitPrivateForMemory(*value, destType);
1248
1249 return {};
1250}
1251
1253 if (!ce->hasAPValueResult())
1254 return {};
1255
1256 QualType retType = ce->getType();
1257 if (ce->isGLValue())
1258 retType = cgm.getASTContext().getLValueReferenceType(retType);
1259
1260 return emitAbstract(ce->getBeginLoc(), ce->getAPValueResult(), retType);
1261}
1262
1264 QualType destType) {
1265 QualType nonMemoryDestType = getNonMemoryType(cgm, destType);
1266 mlir::TypedAttr c = tryEmitPrivate(e, nonMemoryDestType);
1267 if (c) {
1268 mlir::Attribute attr = emitForMemory(c, destType);
1269 return mlir::cast<mlir::TypedAttr>(attr);
1270 }
1271 return nullptr;
1272}
1273
1275 QualType destType) {
1276 QualType nonMemoryDestType = getNonMemoryType(cgm, destType);
1277 mlir::Attribute c = tryEmitPrivate(value, nonMemoryDestType);
1278 return (c ? emitForMemory(c, destType) : nullptr);
1279}
1280
1281mlir::Attribute ConstantEmitter::emitAbstract(const Expr *e,
1282 QualType destType) {
1283 AbstractStateRAII state{*this, true};
1284 mlir::Attribute c = mlir::cast<mlir::Attribute>(tryEmitPrivate(e, destType));
1285 if (!c)
1286 cgm.errorNYI(e->getSourceRange(),
1287 "emitAbstract failed, emit null constaant");
1288 return c;
1289}
1290
1292 const APValue &value,
1293 QualType destType) {
1294 AbstractStateRAII state(*this, true);
1295 mlir::Attribute c = tryEmitPrivate(value, destType);
1296 if (!c)
1297 cgm.errorNYI(loc, "emitAbstract failed, emit null constaant");
1298 return c;
1299}
1300
1301mlir::Attribute ConstantEmitter::emitNullForMemory(mlir::Location loc,
1303 QualType t) {
1304 cir::ConstantOp cstOp =
1305 cgm.emitNullConstant(t, loc).getDefiningOp<cir::ConstantOp>();
1306 assert(cstOp && "expected cir.const op");
1307 return emitForMemory(cgm, cstOp.getValue(), t);
1308}
1309
1310mlir::Attribute ConstantEmitter::emitForMemory(mlir::Attribute c,
1311 QualType destType) {
1312 // For an _Atomic-qualified constant, we may need to add tail padding.
1313 if (destType->getAs<AtomicType>()) {
1314 cgm.errorNYI("emitForMemory: atomic type");
1315 return {};
1316 }
1317
1318 return c;
1319}
1320
1322 mlir::Attribute c,
1323 QualType destType) {
1324 // For an _Atomic-qualified constant, we may need to add tail padding.
1325 if (destType->getAs<AtomicType>()) {
1326 cgm.errorNYI("atomic constants");
1327 }
1328
1329 return c;
1330}
1331
1332mlir::TypedAttr ConstantEmitter::tryEmitPrivate(const Expr *e,
1333 QualType destType) {
1334 assert(!destType->isVoidType() && "can't emit a void constant");
1335
1336 if (mlir::Attribute c =
1337 ConstExprEmitter(*this).Visit(const_cast<Expr *>(e), destType))
1338 return llvm::dyn_cast<mlir::TypedAttr>(c);
1339
1340 Expr::EvalResult result;
1341
1342 bool success = false;
1343
1344 if (destType->isReferenceType())
1345 success = e->EvaluateAsLValue(result, cgm.getASTContext());
1346 else
1347 success =
1348 e->EvaluateAsRValue(result, cgm.getASTContext(), inConstantContext);
1349
1350 if (success && !result.hasSideEffects()) {
1351 mlir::Attribute c = tryEmitPrivate(result.Val, destType);
1352 return llvm::dyn_cast<mlir::TypedAttr>(c);
1353 }
1354
1355 return nullptr;
1356}
1357
1358mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
1359 QualType destType) {
1360 auto &builder = cgm.getBuilder();
1361 switch (value.getKind()) {
1362 case APValue::None:
1364 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate none or indeterminate");
1365 return {};
1366 case APValue::Int: {
1367 mlir::Type ty = cgm.convertType(destType);
1368 if (mlir::isa<cir::BoolType>(ty))
1369 return builder.getCIRBoolAttr(value.getInt().getZExtValue());
1370 assert(mlir::isa<cir::IntType>(ty) && "expected integral type");
1371 return cir::IntAttr::get(ty, value.getInt());
1372 }
1373 case APValue::Float: {
1374 const llvm::APFloat &init = value.getFloat();
1375 if (&init.getSemantics() == &llvm::APFloat::IEEEhalf() &&
1376 !cgm.getASTContext().getLangOpts().NativeHalfType &&
1377 cgm.getASTContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1378 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate half");
1379 return {};
1380 }
1381
1382 mlir::Type ty = cgm.convertType(destType);
1383 assert(mlir::isa<cir::FPTypeInterface>(ty) &&
1384 "expected floating-point type");
1385 return cir::FPAttr::get(ty, init);
1386 }
1387 case APValue::Array: {
1388 const ArrayType *arrayTy = cgm.getASTContext().getAsArrayType(destType);
1389 const QualType arrayElementTy = arrayTy->getElementType();
1390 const unsigned numElements = value.getArraySize();
1391 const unsigned numInitElts = value.getArrayInitializedElts();
1392
1393 mlir::Attribute filler;
1394 if (value.hasArrayFiller()) {
1395 filler = tryEmitPrivate(value.getArrayFiller(), arrayElementTy);
1396 if (!filler)
1397 return {};
1398 }
1399
1401 if (filler && builder.isNullValue(filler))
1402 elements.reserve(numInitElts + 1);
1403 else
1404 elements.reserve(numInitElts);
1405
1406 mlir::Type commonElementType;
1407 for (unsigned i = 0; i < numInitElts; ++i) {
1408 const APValue &arrayElement = value.getArrayInitializedElt(i);
1409 const mlir::Attribute element =
1410 tryEmitPrivateForMemory(arrayElement, arrayElementTy);
1411 if (!element)
1412 return {};
1413
1414 const mlir::TypedAttr elementTyped = mlir::cast<mlir::TypedAttr>(element);
1415 if (i == 0)
1416 commonElementType = elementTyped.getType();
1417 else if (elementTyped.getType() != commonElementType) {
1418 commonElementType = {};
1419 }
1420
1421 elements.push_back(elementTyped);
1422 }
1423
1424 mlir::TypedAttr typedFiller = llvm::cast_or_null<mlir::TypedAttr>(filler);
1425 if (filler && !typedFiller)
1426 cgm.errorNYI("array filler should always be typed");
1427
1428 mlir::Type desiredType = cgm.convertType(destType);
1429 return emitArrayConstant(cgm, desiredType, commonElementType, numElements,
1430 elements, typedFiller);
1431 }
1432 case APValue::Vector: {
1433 const QualType elementType =
1434 destType->castAs<VectorType>()->getElementType();
1435 const unsigned numElements = value.getVectorLength();
1436
1438 elements.reserve(numElements);
1439
1440 for (unsigned i = 0; i < numElements; ++i) {
1441 const mlir::Attribute element =
1442 tryEmitPrivateForMemory(value.getVectorElt(i), elementType);
1443 if (!element)
1444 return {};
1445 elements.push_back(element);
1446 }
1447
1448 const auto desiredVecTy =
1449 mlir::cast<cir::VectorType>(cgm.convertType(destType));
1450
1451 return cir::ConstVectorAttr::get(
1452 desiredVecTy,
1453 mlir::ArrayAttr::get(cgm.getBuilder().getContext(), elements));
1454 }
1456 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate member pointer");
1457 return {};
1458 }
1459 case APValue::LValue:
1460 return ConstantLValueEmitter(*this, value, destType).tryEmit();
1461 case APValue::Struct:
1462 case APValue::Union:
1463 return ConstRecordBuilder::buildRecord(*this, value, destType);
1465 case APValue::ComplexFloat: {
1466 mlir::Type desiredType = cgm.convertType(destType);
1467 auto complexType = mlir::dyn_cast<cir::ComplexType>(desiredType);
1468
1469 mlir::Type complexElemTy = complexType.getElementType();
1470 if (isa<cir::IntType>(complexElemTy)) {
1471 const llvm::APSInt &real = value.getComplexIntReal();
1472 const llvm::APSInt &imag = value.getComplexIntImag();
1473 return cir::ConstComplexAttr::get(builder.getContext(), complexType,
1474 cir::IntAttr::get(complexElemTy, real),
1475 cir::IntAttr::get(complexElemTy, imag));
1476 }
1477
1478 assert(isa<cir::FPTypeInterface>(complexElemTy) &&
1479 "expected floating-point type");
1480 const llvm::APFloat &real = value.getComplexFloatReal();
1481 const llvm::APFloat &imag = value.getComplexFloatImag();
1482 return cir::ConstComplexAttr::get(builder.getContext(), complexType,
1483 cir::FPAttr::get(complexElemTy, real),
1484 cir::FPAttr::get(complexElemTy, imag));
1485 }
1488 cgm.errorNYI(
1489 "ConstExprEmitter::tryEmitPrivate fixed point, addr label diff");
1490 return {};
1491 }
1492 llvm_unreachable("Unknown APValue kind");
1493}
1494
1495mlir::Value CIRGenModule::emitNullConstant(QualType t, mlir::Location loc) {
1496 if (t->getAs<PointerType>()) {
1497 return builder.getNullPtr(getTypes().convertTypeForMem(t), loc);
1498 }
1499
1500 if (getTypes().isZeroInitializable(t))
1501 return builder.getNullValue(getTypes().convertTypeForMem(t), loc);
1502
1503 if (getASTContext().getAsConstantArrayType(t)) {
1504 errorNYI("CIRGenModule::emitNullConstant ConstantArrayType");
1505 }
1506
1507 if (t->isRecordType())
1508 errorNYI("CIRGenModule::emitNullConstant RecordType");
1509
1510 assert(t->isMemberDataPointerType() &&
1511 "Should only see pointers to data members here!");
1512
1513 errorNYI("CIRGenModule::emitNullConstant unsupported type");
1514 return {};
1515}
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
static QualType getNonMemoryType(CodeGenModule &CGM, QualType type)
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp, mlir::ArrayAttr indices={})
Get constant address of a global variable as an MLIR attribute.
cir::BoolAttr getCIRBoolAttr(bool state)
cir::PointerType getPointerTo(mlir::Type ty)
mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
bool hasArrayFiller() const
Definition APValue.h:584
const LValueBase getLValueBase() const
Definition APValue.cpp:983
APValue & getArrayInitializedElt(unsigned I)
Definition APValue.h:576
APSInt & getInt()
Definition APValue.h:489
APValue & getStructField(unsigned i)
Definition APValue.h:617
const FieldDecl * getUnionField() const
Definition APValue.h:629
APSInt & getComplexIntImag()
Definition APValue.h:527
ValueKind getKind() const
Definition APValue.h:461
unsigned getArrayInitializedElts() const
Definition APValue.h:595
APValue & getUnionValue()
Definition APValue.h:633
CharUnits & getLValueOffset()
Definition APValue.cpp:993
APValue & getVectorElt(unsigned I)
Definition APValue.h:563
APValue & getArrayFiller()
Definition APValue.h:587
unsigned getVectorLength() const
Definition APValue.h:571
unsigned getArraySize() const
Definition APValue.h:599
@ Indeterminate
This object has an indeterminate value (C++ [basic.indet]).
Definition APValue.h:131
@ None
There is no such object (it's outside its lifetime).
Definition APValue.h:129
APSInt & getComplexIntReal()
Definition APValue.h:519
APFloat & getComplexFloatImag()
Definition APValue.h:543
APFloat & getComplexFloatReal()
Definition APValue.h:535
APFloat & getFloat()
Definition APValue.h:503
APValue & getStructBase(unsigned i)
Definition APValue.h:612
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3720
QualType getElementType() const
Definition TypeBase.h:3732
cir::ConstRecordAttr getAnonConstRecord(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type ty={})
mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type type={})
bool isNullValue(mlir::Attribute attr) const
cir::RecordType getCompleteRecordType(mlir::ArrayAttr fields, bool packed=false, bool padded=false, llvm::StringRef name="")
void computeGlobalViewIndicesFromFlatOffset(int64_t offset, mlir::Type ty, cir::CIRDataLayout layout, llvm::SmallVectorImpl< int64_t > &indices)
cir::ConstArrayAttr getConstArray(mlir::Attribute attrs, cir::ArrayType arrayTy) const
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...
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
mlir::Type convertType(clang::QualType type)
CIRGenBuilderTy & getBuilder()
ItaniumVTableContext & getItaniumVTableContext()
cir::FuncOp getAddrOfFunction(clang::GlobalDecl gd, mlir::Type funcType=nullptr, bool forVTable=false, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
Return the address of the given function.
cir::GlobalViewAttr getAddrOfGlobalVarAttr(const VarDecl *d)
Return the mlir::GlobalViewAttr for the address of the given global.
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
mlir::Value emitNullConstant(QualType t, mlir::Location loc)
Return the result of value-initializing the given type, i.e.
mlir::ModuleOp getModule() const
CIRGenCXXABI & getCXXABI() const
cir::GlobalViewAttr getAddrOfConstantStringFromLiteral(const StringLiteral *s, llvm::StringRef name=".str")
Return a global symbol reference to a constant array for the given string literal.
mlir::Attribute getConstantArrayFromStringLiteral(const StringLiteral *e)
Return a constant array for the given string.
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
mlir::Attribute emitForMemory(mlir::Attribute c, QualType destType)
mlir::Attribute emitNullForMemory(mlir::Location loc, QualType t)
mlir::TypedAttr tryEmitPrivate(const Expr *e, QualType destType)
mlir::Attribute tryEmitPrivateForVarInit(const VarDecl &d)
mlir::Attribute tryEmitPrivateForMemory(const Expr *e, QualType destTy)
mlir::Attribute emitAbstract(const Expr *e, QualType destType)
Emit the result of the given expression as an abstract constant, asserting that it succeeded.
mlir::Attribute tryEmitForInitializer(const VarDecl &d)
Try to emit the initializer of the given declaration as an abstract constant.
mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d)
Try to emit the initializer of the given declaration as an abstract constant.
mlir::Attribute tryEmitConstantExpr(const ConstantExpr *ce)
SourceLocation getBeginLoc() const LLVM_READONLY
Definition ExprCXX.cpp:575
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Definition DeclCXX.cpp:2999
SourceLocation getBeginLoc() const
Definition ExprCXX.h:1442
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprCXX.h:902
CastKind getCastKind() const
Definition Expr.h:3654
Expr * getSubExpr()
Definition Expr.h:3660
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
int64_t QuantityType
Definition CharUnits.h:40
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits One()
One - Construct a CharUnits quantity of one.
Definition CharUnits.h:58
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
Definition CharUnits.h:201
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Definition CharUnits.h:53
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Definition Expr.h:4818
const Expr * getInitializer() const
Definition Expr.h:3567
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
Definition Expr.h:1082
APValue getAPValueResult() const
Definition Expr.cpp:409
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:1132
bool hasAPValueResult() const
Definition Expr.h:1157
bool hasAttr() const
Definition DeclBase.h:577
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.cpp:4829
This represents one expression.
Definition Expr.h:112
bool isGLValue() const
Definition Expr.h:287
bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsLValue - Evaluate an expression to see if we can fold it to an lvalue with link time known ...
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
Definition Expr.cpp:3665
QualType getType() const
Definition Expr.h:144
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3260
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4767
bool isZeroSize(const ASTContext &Ctx) const
Determine if this field is a subobject of zero size, that is, either a zero-length bit-field or a fie...
Definition Decl.cpp:4707
bool isUnnamedBitField() const
Determines whether this is an unnamed bitfield.
Definition Decl.h:3263
const Expr * getSubExpr() const
Definition Expr.h:1062
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition Decl.h:2376
Expr * getResultExpr()
Return the result expression of this controlling expression.
Definition Expr.h:6396
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:6006
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
Definition Expr.cpp:2457
FieldDecl * getInitializedFieldInUnion()
If this initializes a union, specifies which field in the union to initialize.
Definition Expr.h:5359
const Expr * getInit(unsigned Init) const
Definition Expr.h:5287
const VTableLayout & getVTableLayout(const CXXRecordDecl *RD)
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition ExprCXX.h:4931
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprObjC.h:162
SourceLocation getBeginLoc() const LLVM_READONLY
Definition ExprObjC.h:436
const Expr * getSubExpr() const
Definition Expr.h:2199
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3328
A (possibly-)qualified type.
Definition TypeBase.h:937
bool hasFlexibleArrayMember() const
Definition Decl.h:4342
field_range fields() const
Definition Decl.h:4512
RecordDecl * getDefinitionOrSelf() const
Definition Decl.h:4497
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:334
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:346
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4834
bool isUnion() const
Definition Decl.h:3919
bool isVoidType() const
Definition TypeBase.h:8878
bool isArrayType() const
Definition TypeBase.h:8621
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9165
bool isReferenceType() const
Definition TypeBase.h:8546
bool isMemberDataPointerType() const
Definition TypeBase.h:8614
bool isVectorType() const
Definition TypeBase.h:8661
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9098
bool isRecordType() const
Definition TypeBase.h:8649
Expr * getSubExpr() const
Definition Expr.h:2285
AddressPointLocation getAddressPoint(BaseSubobject Base) const
QualType getType() const
Definition Decl.h:722
Represents a variable declaration or definition.
Definition Decl.h:925
APValue * evaluateValue() const
Attempt to evaluate the value of the initializer attached to this declaration, and produce notes expl...
Definition Decl.cpp:2575
bool hasConstantInitialization() const
Determine whether this variable has constant initialization.
Definition Decl.cpp:2648
const Expr * getInit() const
Definition Decl.h:1367
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1183
Represents a GCC generic vector type.
Definition TypeBase.h:4173
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ComplexType > complexType
const AstTypeMatcher< RecordType > recordType
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition PrimType.h:185
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
Definition DeclBase.h:1288
void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
U cast(CodeGen::Address addr)
Definition Address.h:327
unsigned long uint64_t
long int64_t
#define false
Definition stdbool.h:26
static bool recordZeroInitPadding()
static bool addressPointerAuthInfo()
static bool constEmitterArrayILE()
static bool constEmitterVectorILE()
mlir::Type UCharTy
ClangIR char.
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:645
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:647
bool hasSideEffects() const
Return true if the evaluated expression has side effects.
Definition Expr.h:639