18#include "mlir/IR/Attributes.h"
19#include "mlir/IR/BuiltinAttributeInterfaces.h"
20#include "mlir/IR/BuiltinAttributes.h"
33#include "llvm/ADT/ArrayRef.h"
34#include "llvm/ADT/STLExtras.h"
35#include "llvm/Support/ErrorHandling.h"
52 for (
auto [idx, memberTy] : llvm::enumerate(recordTy.
getMembers())) {
55 mlir::Attribute elt = elements[idx];
61 stored.push_back(elt);
74class RecordBuilderInitList {
77 std::variant<APValue, const InitListExpr *> value;
79 bool holdsExpr()
const {
80 return std::holds_alternative<const InitListExpr *>(value);
83 bool holdsAPValue()
const {
return std::holds_alternative<APValue>(value); }
85 const Expr *getExpr() {
87 return std::get<const InitListExpr *>(value)->getInit(initIdx);
92 return cgm.
getLoc(std::get<const InitListExpr *>(value)->getBeginLoc());
96 assert(holdsAPValue());
98 return std::get<APValue>(value).getUnionValue();
99 return std::get<APValue>(value).getStructField(initIdx);
104 : isUnion(rd->
isUnion()), value(val) {}
106 : isUnion(rd->
isUnion()), value(ile) {
111 if (
auto *
const *ile = std::get_if<const InitListExpr *>(&value))
112 return initIdx >= (*ile)->getNumInits();
117 return !std::get<APValue>(value).isUnion();
119 return initIdx >= std::get<APValue>(value).getStructNumFields();
122 const FieldDecl *getActiveUnionField()
const {
124 return std::get<const InitListExpr *>(value)
125 ->getInitializedFieldInUnion();
126 return std::get<APValue>(value).getUnionField();
135 if (holdsExpr() && isa_and_nonnull<NoInitExpr>(getExpr()))
157 APValue getBase(
unsigned idx) {
162 assert(holdsAPValue());
164 return std::get<APValue>(value).getStructBase(idx);
168 if (holdsExpr() && getExpr()->HasSideEffects(ctx))
176 const Expr *e = getExpr();
184llvm::APInt bitfieldStorageToAPInt(mlir::Attribute
attr,
unsigned storageSize,
188 return llvm::APInt(storageSize, 0);
190 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(
attr))
191 return intAttr.getValue();
195 llvm::APInt result(storageSize, 0);
196 auto elts = mlir::cast<mlir::ArrayAttr>(
197 mlir::cast<cir::ConstArrayAttr>(
attr).getElts());
199 unsigned numBytes = elts.size();
200 for (
unsigned i = 0; i != numBytes; ++i) {
201 unsigned byteIdx = isBigEndian ? numBytes - 1 - i : i;
203 mlir::cast<cir::IntAttr>(elts[i]).getValue().zextOrTrunc(8);
204 result.insertBits(
byte, byteIdx * 8);
209mlir::Attribute apIntToBitfieldStorage(
CIRGenModule &cgm,
210 mlir::Type storageType,
211 const llvm::APInt &value,
214 if (mlir::isa<cir::IntTypeInterface>(storageType))
215 return cir::IntAttr::get(storageType, value);
219 auto arrayTy = mlir::cast<cir::ArrayType>(storageType);
221 unsigned numBytes = arrayTy.getSize();
225 for (
unsigned i = 0; i != numBytes; ++i) {
226 unsigned byteIdx = isBigEndian ? numBytes - 1 - i : i;
227 bytes[i] = cir::IntAttr::get(byteTy, value.extractBits(8, byteIdx * 8));
229 return cir::ConstArrayAttr::get(
230 arrayTy, mlir::ArrayAttr::get(builder.getContext(),
bytes));
240 mlir::Attribute existingVal,
241 cir::IntAttr newVal,
bool isSigned,
245 bitfieldStorageToAPInt(existingVal, bfInfo.
storageSize, isBigEndian);
247 llvm::APInt curValue = newVal.getValue();
252 curValue = curValue.sextOrTrunc(bfInfo.
size);
254 curValue = curValue.zextOrTrunc(bfInfo.
size);
261 curValue = curValue.shl(bfInfo.
offset);
268 return apIntToBitfieldStorage(cgm, bfInfo.
storageType, result, isBigEndian);
274 mlir::Attribute existingVal, mlir::Attribute newVal) {
276 auto intAttr = mlir::dyn_cast<cir::IntAttr>(newVal);
280 auto boolAttr = mlir::cast<cir::BoolAttr>(newVal);
281 intAttr = cir::IntAttr::get(
282 builder.
getUIntNTy(1), llvm::APInt(1, boolAttr.getValue()));
285 return updateBitfieldInit(
286 cgm, existingVal, intAttr,
293 auto typedAttr = mlir::cast<mlir::TypedAttr>(
attr);
294 if (typedAttr.getType() == baseSubobjTy)
297 if (mlir::isa<cir::ZeroAttr>(
attr))
300 auto recordAttr = mlir::cast<cir::ConstRecordAttr>(
attr);
301 mlir::ArrayAttr members = recordAttr.getMembers();
303 members.begin(), members.begin() + baseSubobjTy.
getNumElements());
315 llvm::zip_equal(baseMembers,
316 llvm::map_range(llvm::make_filter_range(
320 [](
const auto &pair) {
321 auto &[member, baseTy] = pair;
322 return mlir::cast<mlir::TypedAttr>(member).getType() == baseTy;
324 "base-subobject member type does not match complete-object member "
325 "type at the same index");
327 return cir::ConstRecordAttr::get(baseSubobjTy,
328 builder.getArrayAttr(baseMembers));
334 RecordBuilderInitList
inits,
bool handleBases,
353 mlir::Attribute eltAttr =
inits.emit(emitter, activeField->
getType());
358 eltAttr = setBitfieldInit(cgm, cirLayout, builder, activeField,
361 return cir::ConstRecordAttr::get(recordTy, builder.getArrayAttr({eltAttr}));
366 if (
auto *cxxrd = dyn_cast<CXXRecordDecl>(rd)) {
371 cir::GlobalViewAttr vptr =
375 assert(vptr &&
"failed to get vtable address point");
387 if (base.isVirtual())
390 const auto *baseDecl = base.getType()->castAsCXXRecordDecl();
392 unsigned curBaseNo = baseNo++;
405 elements[baseFieldIdx] = buildRecordHelper(
406 emitter, baseDecl, vtableBaseTy, RecordBuilderInitList(rd, baseValue),
407 handleBases, baseOff,
true);
410 if (cxxrd->getNumVBases()) {
411 cgm.
errorNYI(cxxrd->getSourceRange(),
412 "buildRecordHelper: virtual base classes");
425 if (
inits.shouldSkip(field)) {
426 inits.advanceSkip(field);
444 mlir::Attribute eltAttr =
inits.emit(emitter, field->
getType());
451 elements[fieldIdx] = setBitfieldInit(cgm, cirLayout, builder, field,
452 elements[fieldIdx], eltAttr);
455 if (
auto expectedTy = mlir::dyn_cast<cir::RecordType>(
457 eltAttr = asBaseSubobject(builder, eltAttr, expectedTy);
459 elements[fieldIdx] = eltAttr;
481 const bool handleBases =
false;
483 return buildRecordHelper(emitter, rd, rd, RecordBuilderInitList(rd, ile),
491 valTy->
castAs<clang::RecordType>()->getDecl()->getDefinitionOrSelf();
492 return buildRecordHelper(emitter, rd, rd, RecordBuilderInitList(rd, val),
509class ConstExprEmitter
510 :
public StmtVisitor<ConstExprEmitter, mlir::Attribute, QualType> {
516 : cgm(emitter.cgm), emitter(emitter) {}
522 mlir::Attribute VisitStmt(Stmt *s, QualType t) {
return {}; }
524 mlir::Attribute VisitConstantExpr(ConstantExpr *ce, QualType t) {
525 if (mlir::Attribute result = emitter.tryEmitConstantExpr(ce))
530 mlir::Attribute VisitParenExpr(ParenExpr *pe, QualType t) {
535 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe,
540 mlir::Attribute VisitGenericSelectionExpr(GenericSelectionExpr *ge,
545 mlir::Attribute VisitChooseExpr(ChooseExpr *ce, QualType t) {
549 mlir::Attribute VisitCompoundLiteralExpr(CompoundLiteralExpr *e, QualType t) {
553 mlir::Attribute VisitCastExpr(
CastExpr *e, QualType destType) {
554 if (
const auto *ece = dyn_cast<ExplicitCastExpr>(e))
555 cgm.emitExplicitCastExprType(ece,
556 const_cast<CIRGenFunction *
>(emitter.cgf));
562 case CK_AddressSpaceConversion:
563 case CK_ReinterpretMemberPointer:
564 cgm.errorNYI(e->
getBeginLoc(),
"ConstExprEmitter::VisitCastExpr");
567 case CK_DerivedToBaseMemberPointer:
568 case CK_BaseToDerivedMemberPointer:
574 case CK_LValueToRValue:
575 case CK_AtomicToNonAtomic:
576 case CK_NonAtomicToAtomic:
578 case CK_ConstructorConversion:
579 return Visit(subExpr, destType);
581 case CK_IntToOCLSampler:
582 llvm_unreachable(
"global sampler variables are not generated");
585 llvm_unreachable(
"saw dependent cast!");
587 case CK_BuiltinFnToFnPtr:
588 llvm_unreachable(
"builtin functions are handled elsewhere");
591 case CK_ObjCObjectLValueCast:
592 case CK_ARCProduceObject:
593 case CK_ARCConsumeObject:
594 case CK_ARCReclaimReturnedObject:
595 case CK_ARCExtendBlockObject:
596 case CK_CopyAndAutoreleaseBlockObject:
604 case CK_LValueBitCast:
605 case CK_LValueToRValueBitCast:
606 case CK_NullToMemberPointer:
607 case CK_UserDefinedConversion:
608 case CK_CPointerToObjCPointerCast:
609 case CK_BlockPointerToObjCPointerCast:
610 case CK_AnyPointerToBlockPointerCast:
611 case CK_ArrayToPointerDecay:
612 case CK_FunctionToPointerDecay:
613 case CK_BaseToDerived:
614 case CK_DerivedToBase:
615 case CK_UncheckedDerivedToBase:
616 case CK_MemberPointerToBoolean:
618 case CK_FloatingRealToComplex:
619 case CK_FloatingComplexToReal:
620 case CK_FloatingComplexToBoolean:
621 case CK_FloatingComplexCast:
622 case CK_FloatingComplexToIntegralComplex:
623 case CK_IntegralRealToComplex:
624 case CK_IntegralComplexToReal:
625 case CK_IntegralComplexToBoolean:
626 case CK_IntegralComplexCast:
627 case CK_IntegralComplexToFloatingComplex:
628 case CK_PointerToIntegral:
629 case CK_PointerToBoolean:
630 case CK_NullToPointer:
631 case CK_IntegralCast:
632 case CK_BooleanToSignedIntegral:
633 case CK_IntegralToPointer:
634 case CK_IntegralToBoolean:
635 case CK_IntegralToFloating:
636 case CK_FloatingToIntegral:
637 case CK_FloatingToBoolean:
638 case CK_FloatingCast:
639 case CK_FloatingToFixedPoint:
640 case CK_FixedPointToFloating:
641 case CK_FixedPointCast:
642 case CK_FixedPointToBoolean:
643 case CK_FixedPointToIntegral:
644 case CK_IntegralToFixedPoint:
645 case CK_ZeroToOCLOpaqueType:
647 case CK_HLSLArrayRValue:
648 case CK_HLSLVectorTruncation:
649 case CK_HLSLMatrixTruncation:
650 case CK_HLSLElementwiseCast:
651 case CK_HLSLAggregateSplatCast:
654 llvm_unreachable(
"Invalid CastKind");
657 mlir::Attribute VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die, QualType t) {
660 return Visit(die->
getExpr(), t);
663 mlir::Attribute VisitExprWithCleanups(ExprWithCleanups *e, QualType t) {
668 mlir::Attribute VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e,
673 mlir::Attribute VisitImplicitValueInitExpr(ImplicitValueInitExpr *e,
675 return cgm.emitNullConstantAttr(t);
678 mlir::Attribute VisitInitListExpr(InitListExpr *ile, QualType t) {
680 return Visit(ile->
getInit(0), t);
690 return ConstRecordBuilder::buildRecord(emitter, ile, t);
703 mlir::Attribute VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e,
705 mlir::Attribute c = Visit(e->
getBase(), destType);
710 "ConstExprEmitter::VisitDesignatedInitUpdateExpr");
714 mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {
720 assert(e->
getNumArgs() == 1 &&
"trivial ctor with > 1 argument");
722 "trivial ctor has argument but isn't a copy/move ctor");
725 assert(cgm.getASTContext().hasSameUnqualifiedType(ty,
arg->getType()) &&
726 "argument to copy ctor is of wrong type");
730 if (
auto const *mte = dyn_cast<MaterializeTemporaryExpr>(arg))
731 return Visit(mte->getSubExpr(), ty);
741 return cgm.getBuilder().getZeroInitAttr(cgm.convertType(ty));
744 mlir::Attribute VisitStringLiteral(StringLiteral *e, QualType t) {
746 return cgm.getConstantArrayFromStringLiteral(e);
749 mlir::Attribute VisitObjCEncodeExpr(ObjCEncodeExpr *e, QualType t) {
750 cgm.errorNYI(e->
getBeginLoc(),
"ConstExprEmitter::VisitObjCEncodeExpr");
754 mlir::Attribute VisitUnaryExtension(
const UnaryOperator *e, QualType t) {
759 mlir::Type convertType(QualType t) {
return cgm.convertType(t); }
766 type.getQualifiers());
779struct ConstantLValue {
780 llvm::PointerUnion<mlir::Value, mlir::Attribute> value;
781 bool hasOffsetApplied;
783 ConstantLValue(std::nullptr_t)
785 ConstantLValue(cir::GlobalViewAttr address)
786 : value(address), hasOffsetApplied(
false) {}
787 ConstantLValue(cir::GlobalOffsetAttr address)
788 : value(address), hasOffsetApplied(
true) {}
789 ConstantLValue(cir::BlockAddrInfoAttr address)
790 : value(address), hasOffsetApplied(
true) {}
792 ConstantLValue() : value(
nullptr), hasOffsetApplied(
false) {}
796class ConstantLValueEmitter
799 ConstantEmitter &emitter;
804 friend StmtVisitorBase;
807 ConstantLValueEmitter(ConstantEmitter &emitter,
const APValue &value,
809 : cgm(emitter.cgm), emitter(emitter), value(value), destType(destType) {}
811 mlir::Attribute tryEmit();
814 mlir::Attribute tryEmitAbsolute(mlir::Type destTy);
815 ConstantLValue tryEmitBase(
const APValue::LValueBase &base);
817 ConstantLValue VisitStmt(
const Stmt *s) {
return nullptr; }
818 ConstantLValue VisitConstantExpr(
const ConstantExpr *e);
819 ConstantLValue VisitCompoundLiteralExpr(
const CompoundLiteralExpr *e);
820 ConstantLValue VisitStringLiteral(
const StringLiteral *e);
821 ConstantLValue VisitObjCBoxedExpr(
const ObjCBoxedExpr *e);
822 ConstantLValue VisitObjCEncodeExpr(
const ObjCEncodeExpr *e);
823 ConstantLValue VisitObjCStringLiteral(
const ObjCStringLiteral *e);
824 ConstantLValue VisitPredefinedExpr(
const PredefinedExpr *e);
825 ConstantLValue VisitAddrLabelExpr(
const AddrLabelExpr *e);
826 ConstantLValue VisitCallExpr(
const CallExpr *e);
827 ConstantLValue VisitBlockExpr(
const BlockExpr *e);
828 ConstantLValue VisitCXXTypeidExpr(
const CXXTypeidExpr *e);
830 VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e);
835 std::optional<mlir::ArrayAttr> getOffsetIndices(mlir::Type ty) {
836 int64_t offset = value.getLValueOffset().getQuantity();
837 cir::CIRDataLayout layout(cgm.getModule());
838 SmallVector<int64_t, 3> idxVec;
839 if (!cgm.getBuilder().computeGlobalViewIndicesFromFlatOffset(
840 offset, ty, layout, idxVec))
843 llvm::SmallVector<mlir::Attribute, 3> indices;
845 mlir::IntegerAttr intAttr = cgm.getBuilder().getI32IntegerAttr(i);
846 indices.push_back(intAttr);
850 return mlir::ArrayAttr{};
851 return cgm.getBuilder().getArrayAttr(indices);
855 ConstantLValue applyOffset(ConstantLValue &c) {
857 if (
auto attr = mlir::dyn_cast<mlir::Attribute>(c.value)) {
858 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(attr)) {
859 auto baseTy = mlir::cast<cir::PointerType>(gv.getType()).getPointee();
860 mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
861 assert(!gv.getIndices() &&
"Global view is already indexed");
862 std::optional<mlir::ArrayAttr> indices = getOffsetIndices(baseTy);
864 return cir::GlobalOffsetAttr::get(
865 destTy, gv.getSymbol(), value.getLValueOffset().getQuantity());
866 return cir::GlobalViewAttr::get(destTy, gv.getSymbol(), *indices);
868 llvm_unreachable(
"Unsupported attribute type to offset");
871 cgm.errorNYI(
"ConstantLValue: non-attribute offset");
878mlir::Attribute ConstantLValueEmitter::tryEmit() {
889 assert((mlir::isa<cir::PointerType>(destTy) ||
890 mlir::isa<cir::IntType>(destTy)) &&
891 "constant lvalue destination must be pointer or integer");
896 return tryEmitAbsolute(destTy);
899 ConstantLValue result = tryEmitBase(base);
902 llvm::PointerUnion<mlir::Value, mlir::Attribute> &value = result.value;
907 if (!result.hasOffsetApplied)
908 value = applyOffset(result).value;
913 if (PointerAuthQualifier pointerAuth = destType.
getPointerAuth()) {
914 cgm.
errorNYI(
"ConstantLValueEmitter: pointer authentication");
920 if (
auto attr = mlir::dyn_cast<mlir::Attribute>(value)) {
921 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(attr))
922 return cir::GlobalViewAttr::get(destTy, gv.getSymbol(), gv.getIndices());
924 if (mlir::isa<cir::PointerType>(destTy))
928 cgm.
errorNYI(
"ConstantLValueEmitter: non-attribute pointer or integer");
934mlir::Attribute ConstantLValueEmitter::tryEmitAbsolute(mlir::Type destTy) {
936 auto destPtrTy = mlir::cast<cir::PointerType>(destTy);
938 destPtrTy, value.getLValueOffset().getQuantity());
942ConstantLValueEmitter::tryEmitBase(
const APValue::LValueBase &base) {
944 if (
const ValueDecl *d = base.
dyn_cast<
const ValueDecl *>()) {
949 if (d->hasAttr<WeakRefAttr>()) {
951 "ConstantLValueEmitter: emit pointer base for weakref");
955 if (
auto *fd = dyn_cast<FunctionDecl>(d)) {
958 mlir::MLIRContext *mlirContext = builder.getContext();
964 cir::PointerType ptrTy =
965 mlir::isa<cir::PointerType>(destTy)
966 ? mlir::cast<cir::PointerType>(destTy)
967 : cir::PointerType::get(fop.getFunctionType());
968 mlir::StringAttr symName = fop.getSymNameAttr();
973 fd->hasAttr<CUDAGlobalAttr>())
974 symName = mlir::cast<cir::GlobalOp>(
977 return cir::GlobalViewAttr::get(
978 ptrTy, mlir::FlatSymbolRefAttr::get(mlirContext, symName));
981 if (
auto *vd = dyn_cast<VarDecl>(d)) {
983 if (!vd->hasLocalStorage()) {
984 if (vd->isFileVarDecl() || vd->hasExternalStorage())
987 if (vd->isLocalVarDecl()) {
996 cgm.
errorNYI(d->getSourceRange(),
"ConstantLValueEmitter: MSGuidDecl");
998 if (
const auto *gcd = dyn_cast<UnnamedGlobalConstantDecl>(d))
1002 if (
const auto *tpo = dyn_cast<TemplateParamObjectDecl>(d))
1010 if (TypeInfoLValue typeInfo = base.
dyn_cast<TypeInfoLValue>())
1012 cgm.
getBuilder().getUnknownLoc(), QualType(typeInfo.getType(), 0)));
1015 return Visit(base.
get<
const Expr *>());
1018ConstantLValue ConstantLValueEmitter::VisitConstantExpr(
const ConstantExpr *e) {
1023static cir::GlobalViewAttr
1038 "file-scope compound literal did not have constant initializer!");
1042 auto typedInit = mlir::cast<mlir::TypedAttr>(c);
1051 gv.setLinkage(cir::GlobalLinkageKind::InternalLinkage);
1052 gv.setAlignment(align.getAsAlign().value());
1061ConstantLValueEmitter::VisitCompoundLiteralExpr(
const CompoundLiteralExpr *e) {
1062 ConstantEmitter compoundLiteralEmitter(cgm, emitter.
cgf);
1068ConstantLValueEmitter::VisitStringLiteral(
const StringLiteral *e) {
1073ConstantLValueEmitter::VisitObjCEncodeExpr(
const ObjCEncodeExpr *e) {
1079ConstantLValueEmitter::VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1081 "ConstantLValueEmitter: objc string literal");
1086ConstantLValueEmitter::VisitObjCBoxedExpr(
const ObjCBoxedExpr *e) {
1092ConstantLValueEmitter::VisitPredefinedExpr(
const PredefinedExpr *e) {
1097ConstantLValueEmitter::VisitAddrLabelExpr(
const AddrLabelExpr *e) {
1103 assert(emitter.
cgf &&
"label address in a constant requires a function");
1104 CIRGenFunction &cgf = *
const_cast<CIRGenFunction *
>(emitter.
cgf);
1106 return cir::BlockAddrInfoAttr::get(&cgf.
getMLIRContext(), func.getSymName(),
1110ConstantLValue ConstantLValueEmitter::VisitCallExpr(
const CallExpr *e) {
1115ConstantLValue ConstantLValueEmitter::VisitBlockExpr(
const BlockExpr *e) {
1121ConstantLValueEmitter::VisitCXXTypeidExpr(
const CXXTypeidExpr *e) {
1130ConstantLValue ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
1131 const MaterializeTemporaryExpr *e) {
1135 return ConstantLValue(
1144 initializeNonAbstract();
1150 initializeNonAbstract();
1156 initializeNonAbstract();
1158 assert(c &&
"couldn't emit constant value non-abstractly?");
1163 assert(initializedNonAbstract &&
1164 "finalizing emitter that was used for abstract emission?");
1165 assert(!finalized &&
"finalizing emitter multiple times");
1166 assert(!gv.isDeclaration());
1175 AbstractStateRAII state(*
this,
true);
1180 assert((!initializedNonAbstract || finalized || failed) &&
1181 "not finalized after being initialized for non-abstract emission");
1185 mlir::Type baseType,
1189 bool asCompleteObject) {
1191 mlir::Type ty = (asCompleteObject ? layout.
getCIRType()
1193 auto recordTy = mlir::cast<cir::RecordType>(ty);
1195 unsigned numElements = rd->
isUnion() ? 1 : recordTy.getNumElements();
1198 auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);
1202 if (base.isVirtual()) {
1219 mlir::Type baseType = recordTy.getElementType(fieldIndex);
1228 if (!field->isBitField() &&
1236 if (field->getIdentifier())
1238 if (
const auto *fieldRD = field->getType()->getAsRecordDecl())
1239 if (fieldRD->findFirstNamedDataMember())
1245 if (cxxrd && asCompleteObject) {
1247 cgm.
errorNYI(vbase.getSourceRange(),
"emitNullConstant: virtual base");
1252 mlir::MLIRContext *mlirContext = recordTy.getContext();
1260 return cir::ConstRecordAttr::get(
1261 recordTy, mlir::ArrayAttr::get(mlirContext, elements));
1270 return cir::ConstRecordAttr::get(
1271 recordTy, mlir::ArrayAttr::get(mlirContext, storedElements));
1276 mlir::Type baseType,
1296 if (
const auto *e = dyn_cast_or_null<CXXConstructExpr>(d.
getInit())) {
1299 return cgm.emitNullConstantAttr(d.
getType());
1306 assert(e &&
"No initializer to emit");
1312 if (mlir::Attribute c = ConstExprEmitter(*this).Visit(
const_cast<Expr *
>(e),
1327 AbstractStateRAII state{*
this,
true};
1337 retType =
cgm.getASTContext().getLValueReferenceType(retType);
1348 return mlir::cast<mlir::TypedAttr>(
attr);
1362 AbstractStateRAII state{*
this,
true};
1363 mlir::Attribute c = mlir::cast<mlir::Attribute>(
tryEmitPrivate(e, destType));
1366 "emitAbstract failed, emit null constaant");
1373 AbstractStateRAII state(*
this,
true);
1376 cgm.errorNYI(loc,
"emitAbstract failed, emit null constaant");
1383 cir::ConstantOp cstOp =
1384 cgm.emitNullConstant(t, loc).getDefiningOp<cir::ConstantOp>();
1385 assert(cstOp &&
"expected cir.const op");
1399 QualType destValueType = at->getValueType();
1402 uint64_t innerSize =
cgm.getASTContext().getTypeSize(destValueType);
1403 uint64_t outerSize =
cgm.getASTContext().getTypeSize(destType);
1404 if (innerSize == outerSize)
1407 assert(innerSize < outerSize &&
"emitted over-large constant for atomic");
1408 cgm.errorNYI(
"emitForMemory: tail padding in atomic initializer");
1414 cgm.errorNYI(
"emitForMemory: zero-extend HLSL bool vectors");
1427 assert(!destType->
isVoidType() &&
"can't emit a void constant");
1429 if (mlir::Attribute c =
1430 ConstExprEmitter(*this).Visit(
const_cast<Expr *
>(e), destType))
1431 return llvm::dyn_cast<mlir::TypedAttr>(c);
1435 bool success =
false;
1445 return llvm::dyn_cast<mlir::TypedAttr>(c);
1453 auto &builder =
cgm.getBuilder();
1457 cgm.errorNYI(
"ConstExprEmitter::tryEmitPrivate none or indeterminate");
1460 mlir::Type ty =
cgm.convertType(destType);
1461 if (mlir::isa<cir::BoolType>(ty))
1463 assert(mlir::isa<cir::IntType>(ty) &&
"expected integral type");
1464 return cir::IntAttr::get(ty, value.
getInt());
1467 mlir::Type ty =
cgm.convertType(destType);
1468 assert(mlir::isa<cir::FPTypeInterface>(ty) &&
1469 "expected floating-point type");
1470 return cir::FPAttr::get(ty, value.
getFloat());
1473 const ArrayType *arrayTy =
cgm.getASTContext().getAsArrayType(destType);
1478 mlir::TypedAttr filler;
1480 mlir::Attribute fillerTemp =
1484 filler = dyn_cast<mlir::TypedAttr>(fillerTemp);
1486 cgm.errorNYI(
"ConstExprEmitter::tryEmitPrivate array filler should "
1493 cir::ArrayType desiredType =
1498 elts.reserve(numInitElts);
1500 elts.reserve(numElements);
1503 for (
unsigned i = 0; i < numInitElts; ++i) {
1505 const mlir::Attribute element =
1510 elts.push_back(element);
1515 elts.insert(elts.end(), numElements - elts.size(), filler);
1518 while (!elts.empty() && builder.
isNullValue(elts.back()))
1523 if (desiredType.getSize() == 0 && numElements > 0) {
1525 cir::ArrayType::get(desiredType.getElementType(), numElements);
1529 return cir::ZeroAttr::get(desiredType);
1531 return cir::ConstArrayAttr::get(
1532 desiredType, mlir::ArrayAttr::get(builder.getContext(), elts));
1540 elements.reserve(numElements);
1542 for (
unsigned i = 0; i < numElements; ++i) {
1543 const mlir::Attribute element =
1547 elements.push_back(element);
1550 const auto desiredVecTy =
1551 mlir::cast<cir::VectorType>(
cgm.convertType(destType));
1553 return cir::ConstVectorAttr::get(
1555 mlir::ArrayAttr::get(
cgm.getBuilder().getContext(), elements));
1564 if (
auto const *cxxDecl = dyn_cast<CXXMethodDecl>(memberDecl)) {
1565 auto ty = mlir::cast<cir::MethodType>(
cgm.convertType(destType));
1566 if (cxxDecl->isVirtual())
1567 return cgm.getCXXABI().buildVirtualMethodAttr(ty, cxxDecl);
1569 cir::FuncOp methodFuncOp =
1570 cgm.getAddrOfFunction(cxxDecl, ty.getMemberFuncTy());
1571 return cgm.getBuilder().getMethodAttr(ty, methodFuncOp);
1574 auto cirTy = mlir::cast<cir::DataMemberType>(
cgm.convertType(destType));
1580 if (
const auto *
fieldDecl = dyn_cast<FieldDecl>(memberDecl);
1586 return cir::DataMemberOffsetAttr::get(cirTy, offset.
getQuantity());
1589 std::optional<llvm::SmallVector<int32_t>> path =
1590 cgm.buildMemberPath(destClass, memberDecl);
1596 return ConstantLValueEmitter(*
this, value, destType).tryEmit();
1599 return ConstRecordBuilder::buildRecord(*
this, value, destType);
1602 mlir::Type desiredType =
cgm.convertType(destType);
1603 auto complexType = mlir::dyn_cast<cir::ComplexType>(desiredType);
1605 mlir::Type complexElemTy =
complexType.getElementType();
1609 return cir::ConstComplexAttr::get(builder.getContext(),
complexType,
1610 cir::IntAttr::get(complexElemTy, real),
1611 cir::IntAttr::get(complexElemTy, imag));
1615 "expected floating-point type");
1618 return cir::ConstComplexAttr::get(builder.getContext(),
complexType,
1619 cir::FPAttr::get(complexElemTy, real),
1620 cir::FPAttr::get(complexElemTy, imag));
1623 mlir::Type ty =
cgm.convertType(destType);
1624 return cir::IntAttr::get(ty, value.
getFixedPoint().getValue());
1634 mlir::Type resultType =
cgm.getTypes().convertType(destType);
1635 auto intResultType = mlir::cast<cir::IntType>(resultType);
1637 return cir::BlockAddrDiffAttr::get(
1638 builder.getContext(), intResultType, func.getSymName(),
1643 cgm.errorNYI(
"ConstExprEmitter::tryEmitPrivate matrix");
1647 llvm_unreachable(
"std::meta::info is consteval-only type");
1649 llvm_unreachable(
"Unknown APValue kind");
1657 mlir::Location loc) {
1663 return builder.getConstNullPtrAttr(
getTypes().convertTypeForMem(t));
1665 if (
getTypes().isZeroInitializable(t))
1666 return builder.getZeroInitAttr(
getTypes().convertTypeForMem(t));
1670 QualType elementTy = cat->getElementType();
1675 auto arrayTy = mlir::cast<cir::ArrayType>(
getTypes().convertTypeForMem(t));
1677 if (builder.isNullValue(elementAttr))
1678 return cir::ZeroAttr::get(arrayTy);
1682 return cir::ConstArrayAttr::get(
1683 arrayTy, mlir::ArrayAttr::get(builder.getContext(), elements));
1686 if (
const RecordType *rt = t->
getAs<RecordType>())
1687 return ::emitNullConstant(*
this, rt->getDecl(),
true);
1690 "Should only see pointers to data members here!");
1697 return ::emitNullConstant(*
this, record,
false);
Defines the clang::ASTContext interface.
static StringRef bytes(const std::vector< T, Allocator > &v)
Defines enum values for all the target-independent builtin functions.
static bool emit(llvm::SmallVectorImpl< std::byte > &Code, const T &Val)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
static QualType getNonMemoryType(CodeGenModule &CGM, QualType type)
static mlir::TypedAttr emitNullConstant(CIRGenModule &cgm, const RecordDecl *rd, bool asCompleteObject)
static mlir::TypedAttr emitNullConstantForBase(CIRGenModule &cgm, mlir::Type baseType, const CXXRecordDecl *baseDecl)
Emit the null constant for a base subobject.
static bool collectStoredInitializers(CIRGenBuilderTy &builder, cir::RecordType recordTy, llvm::ArrayRef< mlir::Attribute > elements, llvm::SmallVectorImpl< mlir::Attribute > &stored)
Collects the initializer elements for the members of recordTy that are stored, in order,...
static cir::GlobalViewAttr tryEmitGlobalCompoundLiteral(ConstantEmitter &emitter, const CompoundLiteralExpr *e)
static ParseState advance(ParseState S, size_t N)
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)
mlir::TypedAttr getZeroInitAttr(mlir::Type ty)
mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value)
C++ view class that accepts both !cir.struct and !cir.union types.
llvm::ArrayRef< mlir::Type > getMembers() const
size_t getNumElements() const
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
bool hasArrayFiller() const
const LValueBase getLValueBase() const
APValue & getArrayInitializedElt(unsigned I)
APSInt & getComplexIntImag()
ValueKind getKind() const
unsigned getArrayInitializedElts() const
APFixedPoint & getFixedPoint()
const ValueDecl * getMemberPointerDecl() const
const AddrLabelExpr * getAddrLabelDiffRHS() const
APValue & getVectorElt(unsigned I)
APValue & getArrayFiller()
unsigned getVectorLength() const
unsigned getArraySize() const
@ Indeterminate
This object has an indeterminate value (C++ [basic.indet]).
@ None
There is no such object (it's outside its lifetime).
APSInt & getComplexIntReal()
APFloat & getComplexFloatImag()
APFloat & getComplexFloatReal()
const AddrLabelExpr * getAddrLabelDiffLHS() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
uint64_t getFieldOffset(const ValueDecl *FD) const
Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
CharUnits getMemberPointerPathAdjustment(const APValue &MP) const
Find the 'this' offset for the member path in a pointer-to-member APValue.
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.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
AddrLabelExpr - The GNU address of label extension, representing &&label.
LabelDecl * getLabel() const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
cir::IntType getUInt8Ty()
cir::DataMemberAttr getDataMemberAttr(cir::DataMemberType ty, llvm::ArrayRef< int32_t > path)
mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr, cir::RecordType recordTy)
bool isNullValue(mlir::Attribute attr) const
cir::IntType getUIntNTy(int n)
virtual mlir::Operation * getKernelHandle(cir::FuncOp fn, GlobalDecl gd)=0
virtual cir::GlobalViewAttr getVTableAddressPointAttr(BaseSubobject base, const CXXRecordDecl *vtableClass)=0
Get the address point of the vtable for the given base subobject as a constant suitable for a global ...
mlir::Operation * curFn
The current function or global initializer that is generated code for.
mlir::MLIRContext & getMLIRContext()
This class organizes the cross-function state that is used while generating CIR code.
cir::GlobalOp getAddrOfUnnamedGlobalConstantDecl(const UnnamedGlobalConstantDecl *gcd)
mlir::Value getNullPointer(cir::PointerType ptrTy, QualType qt, mlir::Location loc)
Get target specific null pointer.
cir::GlobalOp getOrCreateStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd)
clang::ASTContext & getASTContext() const
CIRGenCUDARuntime & getCUDARuntime()
CIRGenBuilderTy & getBuilder()
std::string getUniqueGlobalName(const std::string &baseName)
cir::GlobalOp getAddrOfTemplateParamObject(const TemplateParamObjectDecl *tpo)
Get the GlobalOp of a template parameter object.
mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty, bool forEH=false)
Get the address of the RTTI descriptor for the given type.
mlir::TypedAttr emitNullConstantForBase(const CXXRecordDecl *record)
Return a null constant appropriate for zero-initializing a base class with the given type.
const cir::CIRDataLayout & getDataLayout() const
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.
mlir::TypedAttr emitNullConstantAttr(QualType t)
mlir::Operation * getAddrOfGlobalTemporary(const MaterializeTemporaryExpr *mte, const Expr *init)
Returns a pointer to a global variable representing a temporary with static or thread storage duratio...
static void setInitializer(cir::GlobalOp &op, mlir::Attribute value)
cir::GlobalViewAttr getAddrOfGlobalVarAttr(const VarDecl *d)
Return the mlir::GlobalViewAttr for the address of the given global.
const clang::LangOptions & getLangOpts() const
cir::GlobalOp createGlobalOp(mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::ptr::MemorySpaceAttrInterface addrSpace={}, mlir::Operation *insertPoint=nullptr)
const TargetCIRGenInfo & getTargetCIRGenInfo()
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
mlir::TypedAttr emitNullMemberAttr(QualType t, const MemberPointerType *mpt)
Returns a null attribute to represent either a null method or null data member, depending on the type...
cir::GlobalOp getAddrOfConstantCompoundLiteralIfEmitted(const CompoundLiteralExpr *e)
mlir::Value emitNullConstant(QualType t, mlir::Location loc)
Return the result of value-initializing the given type, i.e.
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.
void setAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *e, cir::GlobalOp gv)
This class handles record and union layout info while lowering AST types to CIR types.
cir::RecordType getCIRType() const
Return the "complete object" LLVM type associated with this record.
cir::RecordType getBaseSubobjectCIRType() const
Return the "base subobject" LLVM type associated with this record.
bool hasNonVirtualBaseCIRField(const CXXRecordDecl *rd) const
const CIRGenBitFieldInfo & getBitFieldInfo(const clang::FieldDecl *fd) const
Return the BitFieldInfo that corresponds to the field FD.
unsigned getCIRFieldNo(const clang::FieldDecl *fd) const
Return cir::RecordType element number that corresponds to the field FD.
bool hasCIRField(const clang::FieldDecl *fd) const
bool isZeroInitializableAsBase() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer when considered as a bas...
unsigned getNonVirtualBaseCIRFieldNo(const CXXRecordDecl *rd) const
const CIRGenRecordLayout & getCIRGenRecordLayout(const clang::RecordDecl *rd)
Return record layout info for the given record decl.
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
void finalize(cir::GlobalOp gv)
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.
bool isInConstantContext() const
mlir::Attribute tryEmitAbstract(const Expr *e, QualType destType)
const CIRGenFunction * cgf
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 emitForInitializer(const APValue &value, QualType destType)
mlir::Attribute tryEmitConstantExpr(const ConstantExpr *ce)
Represents a base class of a C++ class.
Expr * getArg(unsigned Arg)
Return the specified argument.
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Represents a C++ constructor within a class.
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
bool isCopyOrMoveConstructor(unsigned &TypeQuals) const
Determine whether this is a copy or move constructor.
Expr * getExpr()
Get the initialization expression that will be used.
Represents a C++ struct/union/class.
bool isTypeOperand() const
QualType getTypeOperand(const ASTContext &Context) const
Retrieves the type operand of this typeid() expression after various required adjustments (removing r...
Expr * getExprOperand() const
SourceRange getSourceRange() const LLVM_READONLY
CastKind getCastKind() const
This is an opaque type for sizes expressed in character units.
bool isZero() const
Test whether the quantity equals zero.
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
static CharUnits Zero()
Construct a CharUnits quantity of zero.
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
CompoundLiteralExpr - [C99 6.5.2.5].
const Expr * getInitializer() const
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Represents the canonical version of C arrays with a specified constant size.
An expression that occurs in a constant context and the result of evaluating the expression.
APValue getAPValueResult() const
SourceLocation getBeginLoc() const LLVM_READONLY
bool hasAPValueResult() const
SourceLocation getBeginLoc() const LLVM_READONLY
This represents one expression.
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr * > &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
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...
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
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...
bool isUnnamedBitField() const
Determines whether this is an unnamed bitfield.
bool isPotentiallyOverlapping() const
Determine if this field is of potentially-overlapping class type, that is, subobject with the [[no_un...
const Expr * getSubExpr() const
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Expr * getResultExpr()
Return the result expression of this controlling expression.
Describes an C or C++ initializer list.
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
const Expr * getInit(unsigned Init) const
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
A pointer to member type per C++ 8.3.3 - Pointers to members.
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation getBeginLoc() const LLVM_READONLY
const Expr * getSubExpr() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
StringLiteral * getFunctionName()
A (possibly-)qualified type.
PointerAuthQualifier getPointerAuth() const
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
Represents a struct/union/class.
field_range fields() const
Encodes a location in the source.
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
Expr * getReplacement() const
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isPackedVectorBoolType(const ASTContext &ctx) const
CXXRecordDecl * castAsCXXRecordDecl() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isExtVectorBoolType() const
bool isMemberDataPointerType() const
RecordDecl * castAsRecordDecl() const
bool isVectorType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Expr * getSubExpr() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool hasConstantInitialization() const
Determine whether this variable has constant initialization.
const Expr * getInit() const
const APValue * evaluateValue() const
Attempt to evaluate the value of the initializer attached to this declaration, and produce notes expl...
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Represents a GCC generic vector type.
mlir::Type memberStorageType(mlir::Type memberTy)
The storage a member is stored as: the access unit for a bit-field member, and the member type itself...
bool memberOwnsBytes(mlir::Type memberTy)
Whether a record member occupies bytes of its record.
bool isEmptyFieldForLayout(const ASTContext &Ctx, const FieldDecl *FD)
Return true iff the field is "empty", that is, either a zero-width bit-field or an isEmptyRecordForLa...
bool isEmptyRecordForLayout(const ASTContext &Ctx, QualType T)
Return true iff a structure contains only empty base classes (per isEmptyRecordForLayout) and fields ...
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ComplexType > complexType
const internal::VariadicDynCastAllOfMatcher< Decl, FieldDecl > fieldDecl
Matches field declarations.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ SD_Static
Static storage duration.
U cast(CodeGen::Address addr)
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 int64_t
static bool ctorConstLvalueToRvalueConversion()
static bool addressSpace()
static bool addressPointerAuthInfo()
static bool constEmitterArrayILE()
static bool constEmitterVectorILE()
Record with information about how a bitfield should be accessed.
unsigned offset
The offset within a contiguous run of bitfields that are represented as a single "field" within the c...
unsigned storageSize
The storage size in bits which should be used when accessing this bitfield.
unsigned size
The total size of the bit-field, in bits.
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
bool hasSideEffects() const
Return true if the evaluated expression has side effects.