17#include "mlir/IR/Builders.h"
25#include "llvm/IR/Value.h"
32class AggExprEmitter :
public StmtVisitor<AggExprEmitter> {
43 void withReturnValueSlot(
const Expr *e,
44 llvm::function_ref<RValue(ReturnValueSlot)> fn);
46 AggValueSlot ensureSlot(mlir::Location loc, QualType t) {
47 if (!dest.isIgnored())
49 return cgf.createAggTemp(t, loc,
"agg.tmp.ensured");
52 void ensureDest(mlir::Location loc, QualType ty) {
53 if (!dest.isIgnored())
55 dest = cgf.createAggTemp(ty, loc,
"agg.tmp.ensured");
59 AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest)
60 : cgf(cgf), dest(dest) {}
65 void emitAggLoadOfLValue(
const Expr *e);
67 void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy,
68 Expr *exprToVisit, ArrayRef<Expr *> args,
71 void emitFinalDestCopy(QualType
type, RValue src);
74 void emitFinalDestCopy(QualType
type,
const LValue &src,
78 void emitCopy(QualType
type,
const AggValueSlot &dest,
79 const AggValueSlot &src);
81 void emitInitializationToLValue(Expr *e, LValue lv);
83 void emitNullInitializationToLValue(mlir::Location loc, LValue lv);
85 void emitComparisonResult(
const Expr *e, mlir::Location loc,
86 const ComparisonCategoryInfo &cmpInfo,
87 mlir::Value resultValue);
89 void Visit(Expr *e) { StmtVisitor<AggExprEmitter>::Visit(e); }
91 void VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
92 emitAggLoadOfLValue(e);
95 void VisitCallExpr(
const CallExpr *e);
96 void VisitStmtExpr(
const StmtExpr *e) {
97 CIRGenFunction::StmtExprEvaluation eval(cgf);
100 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca, dest);
103 void VisitBinAssign(
const BinaryOperator *e) {
106 assert(cgf.getContext().hasSameUnqualifiedType(e->
getLHS()->
getType(),
108 "Invalid assignment");
113 "block var reference with side effects");
117 LValue lhs = cgf.emitLValue(e->
getLHS());
121 if (lhs.getType()->isAtomicType() ||
122 cgf.isLValueSuitableForInlineAtomic(lhs)) {
125 cgf.emitAtomicStore(dest.asRValue(), lhs,
false);
139 cgf.emitAggExpr(e->
getRHS(), lhsSlot);
142 emitFinalDestCopy(e->
getType(), lhs);
144 if (!dest.isIgnored() && !dest.isExternallyDestructed() &&
150 void VisitDeclRefExpr(DeclRefExpr *e) { emitAggLoadOfLValue(e); }
152 void VisitInitListExpr(InitListExpr *e);
153 void VisitCXXConstructExpr(
const CXXConstructExpr *e);
155 void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef<Expr *> args,
156 FieldDecl *initializedFieldInUnion,
158 void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
159 CIRGenFunction::CXXDefaultInitExprScope Scope(cgf, die);
162 void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *e) {
165 bool wasExternallyDestructed = dest.isExternallyDestructed();
169 dest.setExternallyDestructed();
174 if (!wasExternallyDestructed)
178 void VisitExprWithCleanups(ExprWithCleanups *e);
184 if (
auto *castE = dyn_cast<CastExpr>(op)) {
185 if (castE->getCastKind() ==
kind)
186 return castE->getSubExpr();
194 case CK_LValueToRValueBitCast: {
195 if (dest.isIgnored()) {
201 LValue sourceLV = cgf.emitLValue(e->
getSubExpr());
203 sourceLV.getAddress().withElementType(cgf.getBuilder(), cgf.voidTy);
205 dest.getAddress().withElementType(cgf.getBuilder(), cgf.voidTy);
207 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
209 mlir::Value sizeVal = cgf.getBuilder().getConstInt(
211 cgf.getContext().getTypeSizeInChars(e->
getType()).getQuantity());
212 cgf.getBuilder().createMemCpy(loc, destAddress, sourceAddress, sizeVal);
217 case CK_NonAtomicToAtomic:
218 case CK_AtomicToNonAtomic: {
219 bool isToAtomic = (e->
getCastKind() == CK_NonAtomicToAtomic);
223 QualType valueType = e->
getType();
228 assert(cgf.getContext().hasSameUnqualifiedType(
229 valueType,
atomicType->castAs<AtomicType>()->getValueType()));
233 if (dest.isIgnored() || !cgf.cgm.isPaddedAtomicType(
atomicType))
238 (isToAtomic ? CK_AtomicToNonAtomic : CK_NonAtomicToAtomic);
243 assert(cgf.getContext().hasSameUnqualifiedType(op->
getType(),
245 "peephole significantly changed types?");
252 AggValueSlot valueDest = dest;
256 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
257 if (!dest.isZeroed())
258 cgf.emitNullInitialization(loc, dest.getAddress(),
atomicType);
260 Address valueAddr = cgf.getBuilder().createGetMember(
262 cgf.cgm.getDataLayout());
276 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
277 AggValueSlot atomicSlot = cgf.createAggTemp(
atomicType, loc);
280 Address valueAddr = cgf.getBuilder().createGetMember(
281 loc, atomicSlot.
getAddress(),
"value_addr", 0,
282 cgf.cgm.getDataLayout());
284 return emitFinalDestCopy(valueType, rvalue);
286 case CK_LValueToRValue:
291 "AggExprEmitter: volatile lvalue-to-rvalue cast");
294 case CK_UserDefinedConversion:
295 case CK_ConstructorConversion:
298 "Implicit cast types must be compatible");
302 if (dest.isIgnored()) {
308 Address castPtr = dest.getAddress().withElementType(cgf.getBuilder(),
309 cgf.convertType(ty));
311 cgf.makeAddrLValue(castPtr, ty));
316 std::string(
"AggExprEmitter: VisitCastExpr: ") +
321 void VisitStmt(Stmt *s) {
323 std::string(
"AggExprEmitter::VisitStmt: ") +
326 void VisitParenExpr(ParenExpr *pe) { Visit(pe->
getSubExpr()); }
327 void VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
330 void VisitCoawaitExpr(CoawaitExpr *e) {
331 cgf.emitCoawaitExpr(*e, dest, dest.isIgnored());
333 void VisitCoyieldExpr(CoyieldExpr *e) {
334 cgf.emitCoyieldExpr(*e, dest, dest.isIgnored());
336 void VisitUnaryCoawait(UnaryOperator *e) { Visit(e->
getSubExpr()); }
337 void VisitUnaryExtension(UnaryOperator *e) { Visit(e->
getSubExpr()); }
338 void VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
341 void VisitPackIndexingExpr(PackIndexingExpr *e) {
344 void VisitConstantExpr(ConstantExpr *e) {
348 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e)) {
357 if (dest.mayOverlap()) {
359 cgf.getContext().getTypeInfoDataSizeInChars(ty).Width;
363 if (dataSize != cgf.getContext().getTypeSizeInChars(ty)) {
364 Address temp = cgf.createMemTemp(ty, loc);
365 mlir::Value resultVal = cgf.getBuilder().getConstant(
366 loc, mlir::cast<mlir::TypedAttr>(result));
367 cgf.getBuilder().createStore(loc, resultVal, temp);
368 cgf.getBuilder().createCopy(dest.getAddress(), temp,
375 mlir::Value resultVal = cgf.getBuilder().getConstant(
376 loc, mlir::cast<mlir::TypedAttr>(result));
377 LValue destLVal = cgf.makeAddrLValue(dest.getAddress(), ty);
378 cgf.emitStoreThroughLValue(
RValue::get(resultVal), destLVal);
386 void VisitMemberExpr(MemberExpr *e) { emitAggLoadOfLValue(e); }
387 void VisitUnaryDeref(UnaryOperator *e) { emitAggLoadOfLValue(e); }
388 void VisitStringLiteral(StringLiteral *e) { emitAggLoadOfLValue(e); }
389 void VisitCompoundLiteralExpr(CompoundLiteralExpr *e);
391 void VisitPredefinedExpr(
const PredefinedExpr *e) { emitAggLoadOfLValue(e); }
392 void VisitBinaryOperator(
const BinaryOperator *e) {
394 VisitPointerToDataMemberBinaryOperator(e);
396 cgf.cgm.errorUnsupported(e,
"aggregate binary expression");
398 void VisitPointerToDataMemberBinaryOperator(
const BinaryOperator *e) {
399 LValue lv = cgf.emitPointerToDataMemberBinaryExpr(e);
400 emitFinalDestCopy(e->
getType(), lv);
402 void VisitBinComma(
const BinaryOperator *e) {
403 cgf.emitIgnoredExpr(e->
getLHS());
406 void VisitBinCmp(
const BinaryOperator *e) {
409 const ComparisonCategoryInfo &cmpInfo =
410 cgf.getContext().CompCategories.getInfoForType(e->
getType());
412 "cannot copy non-trivially copyable aggregate");
419 cgf.cgm.errorNYI(e->
getBeginLoc(),
"aggregate three-way comparison");
422 CIRGenBuilderTy &builder = cgf.getBuilder();
425 cgf.cgm.errorNYI(e->
getBeginLoc(),
"VisitBinCmp: complex type");
428 cgf.cgm.errorNYI(e->
getBeginLoc(),
"VisitBinCmp: aggregate type");
430 mlir::Value lhs = cgf.emitAnyExpr(e->
getLHS()).getValue();
431 mlir::Value rhs = cgf.emitAnyExpr(e->
getRHS()).getValue();
433 mlir::Value resultScalar;
442 cir::CmpOrdering ordering = cmpInfo.
isStrong()
443 ? cir::CmpOrdering::Strong
444 : cir::CmpOrdering::Weak;
446 loc, lhs, rhs, ltRes, eqRes, gtRes, ordering);
451 loc, lhs, rhs, ltRes, eqRes, gtRes, unorderedRes);
455 emitComparisonResult(e, loc, cmpInfo, resultScalar);
458 void VisitTypeTraitExpr(
const TypeTraitExpr *e) {
460 "expected a strong_ordering type trait with a stored value");
462 const ComparisonCategoryInfo &cmpInfo =
463 cgf.getContext().CompCategories.getInfoForType(e->
getType());
467 mlir::Value resultValue = cgf.getBuilder().getConstInt(
470 emitComparisonResult(e, loc, cmpInfo, resultValue);
473 void VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
476 void VisitObjCMessageExpr(ObjCMessageExpr *e) {
478 "AggExprEmitter: VisitObjCMessageExpr");
480 void VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
482 "AggExprEmitter: VisitObjCIVarRefExpr");
485 void VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e) {
487 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->
getType());
488 emitInitializationToLValue(e->
getBase(), destLV);
491 void VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e) {
494 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
499 mlir::Value condV = cgf.emitOpOnBoolExpr(loc, e->
getCond());
500 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
503 bool isExternallyDestructed = dest.isExternallyDestructed();
504 bool destructNonTrivialCStruct =
505 !isExternallyDestructed &&
507 isExternallyDestructed |= destructNonTrivialCStruct;
511 cgf.emitIfOnBoolValue(
514 [&](mlir::OpBuilder &b, mlir::Location loc) {
515 eval.beginEvaluation();
517 CIRGenFunction::LexicalScope lexScope{cgf, loc,
518 b.getInsertionBlock()};
519 cgf.curLexScope->setAsTernary();
520 dest.setExternallyDestructed(isExternallyDestructed);
524 eval.endEvaluation();
528 [&](mlir::OpBuilder &b, mlir::Location loc) {
529 eval.beginEvaluation();
531 CIRGenFunction::LexicalScope lexScope{cgf, loc,
532 b.getInsertionBlock()};
539 dest.setExternallyDestructed(isExternallyDestructed);
543 eval.endEvaluation();
547 if (destructNonTrivialCStruct)
550 "Abstract conditional aggregate: destructNonTrivialCStruct");
553 void VisitCXXParenListInitExpr(CXXParenListInitExpr *e) {
559 void VisitArrayInitLoopExpr(
const ArrayInitLoopExpr *e) {
560 CIRGenFunction::OpaqueValueMapping binding(cgf, e->
getCommonExpr());
570 "VisitArrayInitLoopExpr: Non-constant array");
575 emitArrayInit(dest, arrayTy, e->
getType(),
576 const_cast<ArrayInitLoopExpr *
>(e), {}, e->
getSubExpr());
579 void VisitImplicitValueInitExpr(ImplicitValueInitExpr *e) {
582 AggValueSlot slot = ensureSlot(loc, ty);
583 emitNullInitializationToLValue(loc,
586 void VisitNoInitExpr(NoInitExpr *e) {
587 cgf.cgm.errorNYI(e->
getSourceRange(),
"AggExprEmitter: VisitNoInitExpr");
589 void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
590 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
593 void VisitCXXInheritedCtorInitExpr(
const CXXInheritedCtorInitExpr *e) {
603 void VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *e) {
604 ASTContext &ctx = cgf.getContext();
605 CIRGenBuilderTy &builder = cgf.getBuilder();
606 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
608 LValue array = cgf.emitLValue(e->
getSubExpr());
609 assert(array.isSimple() &&
"initializer_list array not a simple lvalue");
610 Address arrayPtr = array.getAddress();
614 assert(
arrayType &&
"std::initializer_list constructed from non-array");
617 assert(record->getNumFields() == 2 &&
618 "Expected std::initializer_list to only have two fields");
621 assert(field != record->field_end() &&
622 ctx.
hasSameType(field->getType()->getPointeeType(),
624 "Expected std::initializer_list first field to be const E *");
627 AggValueSlot dest = ensureSlot(loc, e->
getType());
628 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->
getType());
630 cgf.emitLValueForFieldInitialization(destLV, *field, field->getName());
633 cgf.emitStoreThroughLValue(
RValue::get(arrayStart), start);
635 assert(field != record->field_end() &&
636 "Expected std::initializer_list to have two fields");
640 cgf.emitLValueForFieldInitialization(destLV, *field, field->getName());
643 cgf.emitStoreThroughLValue(
RValue::get(size), endOrLength);
646 assert(field->getType()->isPointerType() &&
647 ctx.
hasSameType(field->getType()->getPointeeType(),
649 "Expected std::initializer_list second field to be const E *");
651 cgf.emitStoreThroughLValue(
RValue::get(arrayEnd), endOrLength);
655 void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) {
657 "AggExprEmitter: VisitCXXScalarValueInitExpr");
659 void VisitCXXTypeidExpr(CXXTypeidExpr *e) { emitAggLoadOfLValue(e); }
660 void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e) {
663 void VisitOpaqueValueExpr(OpaqueValueExpr *e) {
665 "AggExprEmitter: VisitOpaqueValueExpr");
668 void VisitPseudoObjectExpr(PseudoObjectExpr *e) {
670 "AggExprEmitter: VisitPseudoObjectExpr");
673 void VisitVAArgExpr(VAArgExpr *e) {
676 mlir::Value vaArgValue = cgf.emitVAArg(e);
680 Address tmpAddr = cgf.createMemTemp(e->
getType(), loc,
"vaarg.tmp");
683 cgf.emitAggregateStore(vaArgValue, tmpAddr);
686 LValue tmpLValue = cgf.makeAddrLValue(tmpAddr, e->
getType());
689 emitFinalDestCopy(e->
getType(), tmpLValue);
692 void VisitCXXThrowExpr(
const CXXThrowExpr *e) { cgf.emitCXXThrowExpr(e); }
693 void VisitAtomicExpr(AtomicExpr *e) {
694 RValue result = cgf.emitAtomicExpr(e);
695 emitFinalDestCopy(e->
getType(), result);
703void AggExprEmitter::emitAggLoadOfLValue(
const Expr *e) {
712 emitFinalDestCopy(e->
getType(), lv);
715void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
719 emitAggLoadOfLValue(e);
740void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
741 QualType arrayQTy, Expr *e,
742 ArrayRef<Expr *> args, Expr *arrayFiller) {
746 const uint64_t numInitElements = args.size();
750 const QualType elementType =
755 const mlir::Type cirElementType = cgf.
convertType(elementType);
756 const cir::PointerType cirElementPtrType =
759 auto begin = cir::CastOp::create(builder, loc, cirElementPtrType,
760 cir::CastKind::array_to_ptrdecay,
763 const CharUnits elementSize =
765 const CharUnits elementAlign =
772 CIRGenFunction::CleanupDeactivationScope deactivateCleanups(cgf);
776 loc,
"arrayinit.endOfInit");
789 mlir::Value element = begin;
796 for (uint64_t i = 0; i != numInitElements; ++i) {
807 const Address address =
Address(element, cirElementType, elementAlign);
808 const LValue elementLV = cgf.
makeAddrLValue(address, elementType);
809 emitInitializationToLValue(args[i], elementLV);
812 const uint64_t numArrayElements = arrayTy.getSize();
820 if (numInitElements != numArrayElements &&
821 !(dest.
isZeroed() && hasTrivialFiller &&
824 if (numInitElements) {
826 element = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,
841 cir::ConstantOp numArrayElementsConst = builder.
getConstInt(
842 loc, mlir::cast<cir::IntType>(cgf.
ptrDiffTy), numArrayElements);
843 mlir::Value end = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,
844 begin, numArrayElementsConst);
849 [&](mlir::OpBuilder &b, mlir::Location loc) {
850 cir::LoadOp currentElement = builder.
createLoad(loc, tmpAddr);
851 cir::CmpOp cmp = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
852 currentElement, end);
856 [&](mlir::OpBuilder &b, mlir::Location loc) {
857 cir::LoadOp currentElement = builder.
createLoad(loc, tmpAddr);
861 Address(currentElement, cirElementType, elementAlign),
865 if (setArrayInitLoopExprScope)
866 idx = cir::PtrDiffOp::create(b, loc, cgf.
ptrDiffTy, currentElement,
869 CIRGenFunction::ArrayInitLoopExprScope loopExprScope(
870 cgf, setArrayInitLoopExprScope, idx);
873 emitInitializationToLValue(arrayFiller, elementLV);
875 emitNullInitializationToLValue(loc, elementLV);
879 loc, mlir::cast<cir::IntType>(cgf.
ptrDiffTy), 1);
880 auto nextElement = cir::PtrStrideOp::create(
881 builder, loc, cirElementPtrType, currentElement, one);
895void AggExprEmitter::emitFinalDestCopy(QualType
type, RValue src) {
896 assert(src.
isAggregate() &&
"value must be aggregate value!");
902void AggExprEmitter::emitFinalDestCopy(
903 QualType
type,
const LValue &src,
914 cgf.
cgm.
errorNYI(
"emitFinalDestCopy: EVK_RValue & PCK_Struct");
918 cgf.
cgm.
errorNYI(
"emitFinalDestCopy: !EVK_RValue & PCK_Struct");
929 emitCopy(
type, dest, srcAgg);
936void AggExprEmitter::emitCopy(QualType
type,
const AggValueSlot &dest,
937 const AggValueSlot &src) {
950void AggExprEmitter::emitInitializationToLValue(Expr *e, LValue lv) {
951 const QualType
type = lv.getType();
955 return emitNullInitializationToLValue(loc, lv);
961 if (
type->isReferenceType()) {
986void AggExprEmitter::VisitCXXConstructExpr(
const CXXConstructExpr *e) {
991void AggExprEmitter::emitNullInitializationToLValue(mlir::Location loc,
993 const QualType
type = lv.getType();
1003 if (lv.isSimple()) {
1018void AggExprEmitter::emitComparisonResult(
const Expr *e, mlir::Location loc,
1019 const ComparisonCategoryInfo &cmpInfo,
1020 mlir::Value resultValue) {
1022 ensureDest(loc, e->
getType());
1029 destLVal, resultField, resultField->
getName());
1033void AggExprEmitter::VisitLambdaExpr(
LambdaExpr *e) {
1034 CIRGenFunction::SourceLocRAIIObject loc{cgf, e->
getSourceRange()};
1040 CIRGenFunction::CleanupDeactivationScope deactivationScope(cgf);
1042 for (
auto [curField, capture, captureInit] : llvm::zip(
1045 llvm::StringRef fieldName = curField->getName();
1046 if (capture.capturesVariable()) {
1047 assert(!curField->isBitField() &&
"lambdas don't have bitfield members!");
1048 ValueDecl *v = capture.getCapturedVar();
1051 }
else if (capture.capturesThis()) {
1061 if (curField->hasCapturedVLAType())
1064 emitInitializationToLValue(captureInit, lv);
1068 curField->getType().isDestructedType()) {
1069 assert(lv.isSimple());
1071 curField->getType(),
1077void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1078 CIRGenFunction::FullExprCleanupScope fullExprScope(cgf, e->
getSubExpr());
1082void AggExprEmitter::VisitCallExpr(
const CallExpr *e) {
1088 withReturnValueSlot(
1089 e, [&](ReturnValueSlot slot) {
return cgf.
emitCallExpr(e, slot); });
1092void AggExprEmitter::withReturnValueSlot(
1093 const Expr *e, llvm::function_ref<RValue(ReturnValueSlot)> fn) {
1094 QualType retTy = e->
getType();
1097 bool requiresDestruction =
1099 if (requiresDestruction)
1102 "withReturnValueSlot: return value requiring destruction is NYI");
1117 fn(ReturnValueSlot(retAddr));
1120void AggExprEmitter::VisitInitListExpr(InitListExpr *e) {
1122 llvm_unreachable(
"GNU array range designator extension");
1127 visitCXXParenListOrInitListExpr(
1131void AggExprEmitter::visitCXXParenListOrInitListExpr(
1132 Expr *e, ArrayRef<Expr *> args, FieldDecl *initializedFieldInUnion,
1133 Expr *arrayFiller) {
1136 const AggValueSlot dest = ensureSlot(loc, e->
getType());
1139 cir::ArrayType arrayTy =
1146 "visitCXXParenListOrInitListExpr variable array type");
1152 "visitCXXParenListOrInitListExpr array type");
1162 unsigned numInitElements = args.size();
1167 CIRGenFunction::CleanupDeactivationScope deactivateCleanups(cgf);
1169 unsigned curInitIndex = 0;
1172 if (
auto *cxxrd = dyn_cast<CXXRecordDecl>(record)) {
1173 assert(numInitElements >= cxxrd->getNumBases() &&
1174 "missing initializer for base class");
1175 for (
auto &base : cxxrd->bases()) {
1176 assert(!base.isVirtual() &&
"should not see vbases here");
1177 CXXRecordDecl *baseRD = base.getType()->getAsCXXRecordDecl();
1189 base.getType().isDestructedType())
1195 CIRGenFunction::FieldConstructionScope fcScope(cgf, dest.
getAddress());
1199 if (record->isUnion()) {
1202 if (!initializedFieldInUnion) {
1207 assert(llvm::all_of(record->fields(),
1208 [](
const FieldDecl *f) {
1209 return f->isUnnamedBitField() ||
1210 f->isAnonymousStructOrUnion();
1212 "Only unnamed bitfields or anonymous class allowed");
1217 FieldDecl *initedField = initializedFieldInUnion;
1220 destLV, initedField, initedField->
getName());
1222 if (numInitElements) {
1224 emitInitializationToLValue(args[0], fieldLV);
1227 emitNullInitializationToLValue(loc, fieldLV);
1234 for (
const FieldDecl *field : record->fields()) {
1236 if (field->getType()->isIncompleteArrayType())
1240 if (field->isUnnamedBitField())
1246 if (curInitIndex == numInitElements && dest.
isZeroed() &&
1254 if (curInitIndex < numInitElements) {
1256 CIRGenFunction::SourceLocRAIIObject loc{cgf, record->getSourceRange()};
1257 emitInitializationToLValue(args[curInitIndex++], lv);
1267 field->getType().isDestructedType()) {
1268 assert(lv.isSimple());
1298 getContext().getASTRecordLayout(baseRD).getSize() <=
1307 AggExprEmitter(*
this, slot).Visit(
const_cast<Expr *
>(e));
1322 assert((record->hasTrivialCopyConstructor() ||
1323 record->hasTrivialCopyAssignment() ||
1324 record->hasTrivialMoveConstructor() ||
1325 record->hasTrivialMoveAssignment() ||
1326 record->hasAttr<TrivialABIAttr>() || record->isUnion()) &&
1327 "Trying to aggregate-copy a type without a trivial copy/move "
1328 "constructor or assignment operator");
1330 if (record->isEmpty())
1353 typeInfo =
getContext().getTypeInfoDataSizeInChars(ty);
1355 typeInfo =
getContext().getTypeInfoInChars(ty);
1361 cgm.errorNYI(
"emitAggregateCopy: GC");
1367 bool skipTailPadding =
1368 mayOverlap && dataSize !=
getContext().getTypeSizeInChars(ty);
1372 builder.createCopy(destPtr, srcPtr, isVolatile, skipTailPadding);
static Expr * findPeephole(Expr *op, CastKind kind, const ASTContext &ctx)
Attempt to look through various unimportant expressions to find a cast of the given kind.
Defines the clang::Expr interface and subclasses for C++ expressions.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
cir::ConditionOp createCondition(mlir::Value condition)
Create a loop condition.
cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base, mlir::Value stride)
cir::PointerType getPointerTo(mlir::Type ty)
cir::DoWhileOp createDoWhile(mlir::Location loc, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> condBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> bodyBuilder)
Create a do-while operation.
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
const ConstantArrayType * getAsConstantArrayType(QualType T) const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
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.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
llvm::APInt getArraySize() const
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Expr * getSubExpr() const
Get the initializer to use for each array element.
QualType getElementType() const
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getExprLoc() const
mlir::ptr::MemorySpaceAttrInterface getAddressSpace() const
mlir::Value getPointer() const
mlir::Type getElementType() const
clang::CharUnits getAlignment() const
mlir::Value emitRawPointer() const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
IsZeroed_t isZeroed() const
Overlap_t mayOverlap() const
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
IsDestructed_t isExternallyDestructed() const
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
Address getAddress() const
void setExternallyDestructed(bool destructed=true)
static AggValueSlot ignored()
Returns an aggregate value slot indicating that the aggregate value is being ignored.
IsAliased_t isPotentiallyAliased() const
clang::Qualifiers getQualifiers() const
void setVolatile(bool flag)
cir::CmpThreeWayOp createThreeWayCmpTotalOrdering(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, const llvm::APSInt <Res, const llvm::APSInt &eqRes, const llvm::APSInt >Res, cir::CmpOrdering ordering)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false, bool isNontemporal=false)
cir::CmpThreeWayOp createThreeWayCmpPartialOrdering(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, const llvm::APSInt <Res, const llvm::APSInt &eqRes, const llvm::APSInt >Res, const llvm::APSInt &unorderedRes)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, bool isNontemporal=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
static bool hasScalarEvaluationKind(clang::QualType type)
mlir::Type convertType(clang::QualType t)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
CIRGenTypes & getTypes() const
const clang::LangOptions & getLangOpts() const
cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, bool insertIntoFnEntryBlock=false)
This creates an alloca and inserts it into the entry block if ArraySize is nullptr,...
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
void emitAggregateCopy(LValue dest, LValue src, QualType eltTy, AggValueSlot::Overlap_t mayOverlap, bool isVolatile=false)
Emit an aggregate copy.
void pushIrregularPartialArrayCleanup(mlir::Value arrayBegin, Address arrayEndPointer, QualType elementType, CharUnits elementAlign, Destroyer *destroyer)
Push an EH cleanup to destroy already-constructed elements of the given array.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty)
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
void pushDestroyAndDeferDeactivation(QualType::DestructionKind dtorKind, Address addr, QualType type)
void emitScalarInit(const clang::Expr *init, LValue lvalue, bool capturedByInit=false)
AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *fd)
RValue emitAtomicLoad(LValue lvalue, SourceLocation loc, AggValueSlot slot=AggValueSlot::ignored())
void emitCXXConstructExpr(const clang::CXXConstructExpr *e, AggValueSlot dest)
LValue emitAggExprToLValue(const Expr *e)
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, LValueBaseInfo baseInfo, bool isInit=false, bool isNontemporal=false)
static bool hasAggregateEvaluationKind(clang::QualType type)
LValue emitLValueForFieldInitialization(LValue base, const clang::FieldDecl *field, llvm::StringRef fieldName)
Like emitLValueForField, excpet that if the Field is a reference, this will return the address of the...
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
Address getAddressOfDirectBaseInCompleteClass(mlir::Location loc, Address value, const CXXRecordDecl *derived, const CXXRecordDecl *base, bool baseIsVirtual)
Convert the given pointer to a complete class to the given direct base.
CIRGenBuilderTy & getBuilder()
AggValueSlot::Overlap_t getOverlapForBaseInit(const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual)
Determine whether a base class initialization may overlap some other object.
Destroyer * getDestroyer(clang::QualType::DestructionKind kind)
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
clang::ASTContext & getContext() const
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
bool isLValueSuitableForInlineAtomic(LValue lv)
An LValue is a candidate for having its loads and stores be made atomic if we are operating under /vo...
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
mlir::Value emitNullConstant(QualType t, mlir::Location loc)
Return the result of value-initializing the given type, i.e.
llvm::DenseMap< const clang::FieldDecl *, llvm::StringRef > lambdaFieldToName
Keep a map between lambda fields and names, this needs to be per module since lambdas might get gener...
bool isZeroInitializable(clang::QualType ty)
Return whether a type can be zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
Address getAddress() const
Address getAggregateAddress() const
Return the value of the address of the aggregate.
static RValue get(mlir::Value v)
static RValue getAggregate(Address addr, bool isVolatile=false)
Convert an Address to an RValue.
CXXTemporary * getTemporary()
const Expr * getSubExpr() const
Expr * getExpr()
Get the initialization expression that will be used.
bool constructsVBase() const
Determine whether this constructor is actually constructing a base class (rather than a complete obje...
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will call.
bool inheritedFromVBase() const
Determine whether the inherited constructor is inherited from a virtual base of the object we constru...
MutableArrayRef< Expr * > getInitExprs()
FieldDecl * getInitializedFieldInUnion()
Represents a C++ struct/union/class.
bool isTriviallyCopyable() const
Determine whether this class is considered trivially copyable per (C++11 [class]p6).
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
CastKind getCastKind() const
static const char * getCastKindName(CastKind CK)
This is an opaque type for sizes expressed in character units.
bool isZero() const
Test whether the quantity equals zero.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
bool isPartial() const
True iff the comparison is not totally ordered.
const ValueInfo * getLess() const
const ValueInfo * getUnordered() const
const CXXRecordDecl * Record
The declaration for the comparison category type from the standard library.
const ValueInfo * getValueInfo(ComparisonCategoryResult ValueKind) const
bool isStrong() const
True iff the comparison is "strong".
const ValueInfo * getGreater() const
const ValueInfo * getEqualOrEquiv() const
const Expr * getInitializer() const
InitListExpr * getUpdater() const
This represents one expression.
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
const Expr * getSubExpr() const
Expr * getResultExpr()
Return the result expression of this controlling expression.
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
FieldDecl * getInitializedFieldInUnion()
If this initializes a union, specifies which field in the union to initialize.
bool hadArrayRangeDesignator() const
Expr * getArrayFiller()
If this initializer list initializes an array with more elements than there are initializers in the l...
const Expr * getInit(unsigned Init) const
ArrayRef< Expr * > inits() const
llvm::iterator_range< capture_init_iterator > capture_inits()
Retrieve the initialization expressions for this lambda's captures.
capture_range captures() const
Retrieve this lambda's captures.
CXXRecordDecl * getLambdaClass() const
Retrieve the class that corresponds to the lambda.
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Expr * getSelectedExpr() const
const Expr * getSubExpr() const
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
bool isPODType(const ASTContext &Context) const
Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
@ PCK_Struct
The type is a struct containing a field whose type is neither PCK_Trivial nor PCK_VolatileTrivial.
Represents a struct/union/class.
field_range fields() const
specific_decl_iterator< FieldDecl > field_iterator
field_iterator field_begin() const
CompoundStmt * getSubStmt()
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...
const char * getStmtClassName() const
Expr * getReplacement() const
bool isStoredAsComparisonResult() const
const APValue & getAPValue() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool isPointerType() const
bool isReferenceType() const
bool isVariableArrayType() const
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
bool isAnyComplexType() const
bool isMemberPointerType() const
bool isRealFloatingType() const
Floating point categories.
bool isNullPtrType() const
bool isRecordType() const
Expr * getSubExpr() const
bool isTrivialFiller(const Expr *E)
Check whether E is a trivial array filler, that is, one that is equivalent to zero-initialization.
bool isBlockVarRef(const Expr *E)
Check whether the value of E is possibly a reference to or into a __block variable.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
const AstTypeMatcher< AtomicType > atomicType
@ Address
A pointer to a ValueDecl.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
CastKind
CastKind - The kind of operation required for a conversion.
U cast(CodeGen::Address addr)
static bool emitLifetimeMarkers()
static bool aggValueSlotDestructedFlag()
static bool aggValueSlotGC()
static bool aggValueSlotAlias()
static bool aggEmitFinalDestCopyRValue()
static bool aggValueSlotVolatile()
static bool cudaSupport()
static bool incrementProfileCounter()
clang::CharUnits getPointerAlign() const
llvm::APSInt getIntValue() const
Get the constant integer value used by this variable to represent the comparison category result type...