17#include "mlir/IR/Builders.h"
24#include "llvm/IR/Value.h"
31class AggExprEmitter :
public StmtVisitor<AggExprEmitter> {
42 void withReturnValueSlot(
const Expr *e,
43 llvm::function_ref<RValue(ReturnValueSlot)> fn);
45 AggValueSlot ensureSlot(mlir::Location loc, QualType t) {
46 if (!dest.isIgnored())
48 return cgf.createAggTemp(t, loc,
"agg.tmp.ensured");
51 void ensureDest(mlir::Location loc, QualType ty) {
52 if (!dest.isIgnored())
54 dest = cgf.createAggTemp(ty, loc,
"agg.tmp.ensured");
58 AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest)
59 : cgf(cgf), dest(dest) {}
64 void emitAggLoadOfLValue(
const Expr *e);
66 void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy,
67 Expr *exprToVisit, ArrayRef<Expr *> args,
70 void emitFinalDestCopy(QualType
type, RValue src);
73 void emitFinalDestCopy(QualType
type,
const LValue &src,
77 void emitCopy(QualType
type,
const AggValueSlot &dest,
78 const AggValueSlot &src);
80 void emitInitializationToLValue(Expr *e, LValue lv);
82 void emitNullInitializationToLValue(mlir::Location loc, LValue lv);
84 void emitComparisonResult(
const Expr *e, mlir::Location loc,
85 const ComparisonCategoryInfo &cmpInfo,
86 mlir::Value resultValue);
88 void Visit(Expr *e) { StmtVisitor<AggExprEmitter>::Visit(e); }
90 void VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
91 emitAggLoadOfLValue(e);
94 void VisitCallExpr(
const CallExpr *e);
95 void VisitStmtExpr(
const StmtExpr *e) {
96 CIRGenFunction::StmtExprEvaluation eval(cgf);
99 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca, dest);
102 void VisitBinAssign(
const BinaryOperator *e) {
105 assert(cgf.getContext().hasSameUnqualifiedType(e->
getLHS()->
getType(),
107 "Invalid assignment");
112 "block var reference with side effects");
116 LValue lhs = cgf.emitLValue(e->
getLHS());
120 if (lhs.getType()->isAtomicType() ||
121 cgf.isLValueSuitableForInlineAtomic(lhs)) {
124 cgf.emitAtomicStore(dest.asRValue(), lhs,
false);
138 cgf.emitAggExpr(e->
getRHS(), lhsSlot);
141 emitFinalDestCopy(e->
getType(), lhs);
143 if (!dest.isIgnored() && !dest.isExternallyDestructed() &&
149 void VisitDeclRefExpr(DeclRefExpr *e) { emitAggLoadOfLValue(e); }
151 void VisitInitListExpr(InitListExpr *e);
152 void VisitCXXConstructExpr(
const CXXConstructExpr *e);
154 void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef<Expr *> args,
155 FieldDecl *initializedFieldInUnion,
157 void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
158 CIRGenFunction::CXXDefaultInitExprScope Scope(cgf, die);
161 void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *e) {
164 bool wasExternallyDestructed = dest.isExternallyDestructed();
168 dest.setExternallyDestructed();
173 if (!wasExternallyDestructed)
177 void VisitExprWithCleanups(ExprWithCleanups *e);
183 if (
auto *castE = dyn_cast<CastExpr>(op)) {
184 if (castE->getCastKind() ==
kind)
185 return castE->getSubExpr();
193 case CK_LValueToRValueBitCast: {
194 if (dest.isIgnored()) {
200 LValue sourceLV = cgf.emitLValue(e->
getSubExpr());
202 sourceLV.getAddress().withElementType(cgf.getBuilder(), cgf.voidTy);
204 dest.getAddress().withElementType(cgf.getBuilder(), cgf.voidTy);
206 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
208 mlir::Value sizeVal = cgf.getBuilder().getConstInt(
210 cgf.getContext().getTypeSizeInChars(e->
getType()).getQuantity());
211 cgf.getBuilder().createMemCpy(loc, destAddress, sourceAddress, sizeVal);
216 case CK_NonAtomicToAtomic:
217 case CK_AtomicToNonAtomic: {
218 bool isToAtomic = (e->
getCastKind() == CK_NonAtomicToAtomic);
222 QualType valueType = e->
getType();
227 assert(cgf.getContext().hasSameUnqualifiedType(
228 valueType,
atomicType->castAs<AtomicType>()->getValueType()));
232 if (dest.isIgnored() || !cgf.cgm.isPaddedAtomicType(
atomicType))
237 (isToAtomic ? CK_AtomicToNonAtomic : CK_NonAtomicToAtomic);
242 assert(cgf.getContext().hasSameUnqualifiedType(op->
getType(),
244 "peephole significantly changed types?");
251 AggValueSlot valueDest = dest;
255 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
256 if (!dest.isZeroed())
257 cgf.emitNullInitialization(loc, dest.getAddress(),
atomicType);
259 Address valueAddr = cgf.getBuilder().createGetMember(
260 loc, valueDest.
getAddress(),
"value_addr", 0);
274 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
275 AggValueSlot atomicSlot = cgf.createAggTemp(
atomicType, loc);
278 Address valueAddr = cgf.getBuilder().createGetMember(
279 loc, atomicSlot.
getAddress(),
"value_addr", 0);
281 return emitFinalDestCopy(valueType, rvalue);
283 case CK_LValueToRValue:
288 "AggExprEmitter: volatile lvalue-to-rvalue cast");
291 case CK_UserDefinedConversion:
292 case CK_ConstructorConversion:
295 "Implicit cast types must be compatible");
299 if (dest.isIgnored()) {
305 Address castPtr = dest.getAddress().withElementType(cgf.getBuilder(),
306 cgf.convertType(ty));
308 cgf.makeAddrLValue(castPtr, ty));
313 std::string(
"AggExprEmitter: VisitCastExpr: ") +
318 void VisitStmt(Stmt *s) {
320 std::string(
"AggExprEmitter::VisitStmt: ") +
323 void VisitParenExpr(ParenExpr *pe) { Visit(pe->
getSubExpr()); }
324 void VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
327 void VisitCoawaitExpr(CoawaitExpr *e) {
328 cgf.cgm.errorNYI(e->
getSourceRange(),
"AggExprEmitter: VisitCoawaitExpr");
330 void VisitCoyieldExpr(CoyieldExpr *e) {
331 cgf.cgm.errorNYI(e->
getSourceRange(),
"AggExprEmitter: VisitCoyieldExpr");
333 void VisitUnaryCoawait(UnaryOperator *e) {
334 cgf.cgm.errorNYI(e->
getSourceRange(),
"AggExprEmitter: VisitUnaryCoawait");
336 void VisitUnaryExtension(UnaryOperator *e) { Visit(e->
getSubExpr()); }
337 void VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
340 void VisitConstantExpr(ConstantExpr *e) {
343 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e)) {
344 mlir::Value resultVal = cgf.getBuilder().getConstant(
345 cgf.getLoc(e->
getSourceRange()), mlir::cast<mlir::TypedAttr>(result));
346 LValue destLVal = cgf.makeAddrLValue(dest.getAddress(), e->
getType());
347 cgf.emitStoreThroughLValue(
RValue::get(resultVal), destLVal);
355 void VisitMemberExpr(MemberExpr *e) { emitAggLoadOfLValue(e); }
356 void VisitUnaryDeref(UnaryOperator *e) { emitAggLoadOfLValue(e); }
357 void VisitStringLiteral(StringLiteral *e) { emitAggLoadOfLValue(e); }
358 void VisitCompoundLiteralExpr(CompoundLiteralExpr *e);
360 void VisitPredefinedExpr(
const PredefinedExpr *e) { emitAggLoadOfLValue(e); }
361 void VisitBinaryOperator(
const BinaryOperator *e) {
363 VisitPointerToDataMemberBinaryOperator(e);
365 cgf.cgm.errorUnsupported(e,
"aggregate binary expression");
367 void VisitPointerToDataMemberBinaryOperator(
const BinaryOperator *e) {
368 LValue lv = cgf.emitPointerToDataMemberBinaryExpr(e);
369 emitFinalDestCopy(e->
getType(), lv);
371 void VisitBinComma(
const BinaryOperator *e) {
372 cgf.emitIgnoredExpr(e->
getLHS());
375 void VisitBinCmp(
const BinaryOperator *e) {
378 const ComparisonCategoryInfo &cmpInfo =
379 cgf.getContext().CompCategories.getInfoForType(e->
getType());
381 "cannot copy non-trivially copyable aggregate");
388 cgf.cgm.errorNYI(e->
getBeginLoc(),
"aggregate three-way comparison");
391 CIRGenBuilderTy &builder = cgf.getBuilder();
394 cgf.cgm.errorNYI(e->
getBeginLoc(),
"VisitBinCmp: complex type");
397 cgf.cgm.errorNYI(e->
getBeginLoc(),
"VisitBinCmp: aggregate type");
399 mlir::Value lhs = cgf.emitAnyExpr(e->
getLHS()).getValue();
400 mlir::Value rhs = cgf.emitAnyExpr(e->
getRHS()).getValue();
402 mlir::Value resultScalar;
411 cir::CmpOrdering ordering = cmpInfo.
isStrong()
412 ? cir::CmpOrdering::Strong
413 : cir::CmpOrdering::Weak;
415 loc, lhs, rhs, ltRes, eqRes, gtRes, ordering);
420 loc, lhs, rhs, ltRes, eqRes, gtRes, unorderedRes);
424 emitComparisonResult(e, loc, cmpInfo, resultScalar);
427 void VisitTypeTraitExpr(
const TypeTraitExpr *e) {
429 "expected a strong_ordering type trait with a stored value");
431 const ComparisonCategoryInfo &cmpInfo =
432 cgf.getContext().CompCategories.getInfoForType(e->
getType());
436 mlir::Value resultValue = cgf.getBuilder().getConstInt(
439 emitComparisonResult(e, loc, cmpInfo, resultValue);
442 void VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
445 void VisitObjCMessageExpr(ObjCMessageExpr *e) {
447 "AggExprEmitter: VisitObjCMessageExpr");
449 void VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
451 "AggExprEmitter: VisitObjCIVarRefExpr");
454 void VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e) {
456 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->
getType());
457 emitInitializationToLValue(e->
getBase(), destLV);
460 void VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e) {
463 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
468 mlir::Value condV = cgf.emitOpOnBoolExpr(loc, e->
getCond());
469 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
472 bool isExternallyDestructed = dest.isExternallyDestructed();
473 bool destructNonTrivialCStruct =
474 !isExternallyDestructed &&
476 isExternallyDestructed |= destructNonTrivialCStruct;
480 cgf.emitIfOnBoolValue(
483 [&](mlir::OpBuilder &b, mlir::Location loc) {
484 eval.beginEvaluation();
486 CIRGenFunction::LexicalScope lexScope{cgf, loc,
487 b.getInsertionBlock()};
488 cgf.curLexScope->setAsTernary();
489 dest.setExternallyDestructed(isExternallyDestructed);
493 eval.endEvaluation();
497 [&](mlir::OpBuilder &b, mlir::Location loc) {
498 eval.beginEvaluation();
500 CIRGenFunction::LexicalScope lexScope{cgf, loc,
501 b.getInsertionBlock()};
508 dest.setExternallyDestructed(isExternallyDestructed);
512 eval.endEvaluation();
516 if (destructNonTrivialCStruct)
519 "Abstract conditional aggregate: destructNonTrivialCStruct");
522 void VisitCXXParenListInitExpr(CXXParenListInitExpr *e) {
528 void VisitArrayInitLoopExpr(
const ArrayInitLoopExpr *e) {
529 CIRGenFunction::OpaqueValueMapping binding(cgf, e->
getCommonExpr());
539 "VisitArrayInitLoopExpr: Non-constant array");
544 emitArrayInit(dest, arrayTy, e->
getType(),
545 const_cast<ArrayInitLoopExpr *
>(e), {}, e->
getSubExpr());
548 void VisitImplicitValueInitExpr(ImplicitValueInitExpr *e) {
551 AggValueSlot slot = ensureSlot(loc, ty);
552 emitNullInitializationToLValue(loc,
555 void VisitNoInitExpr(NoInitExpr *e) {
556 cgf.cgm.errorNYI(e->
getSourceRange(),
"AggExprEmitter: VisitNoInitExpr");
558 void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
559 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
562 void VisitCXXInheritedCtorInitExpr(
const CXXInheritedCtorInitExpr *e) {
572 void VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *e) {
573 ASTContext &ctx = cgf.getContext();
574 CIRGenBuilderTy &builder = cgf.getBuilder();
575 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
577 LValue array = cgf.emitLValue(e->
getSubExpr());
578 assert(array.isSimple() &&
"initializer_list array not a simple lvalue");
579 Address arrayPtr = array.getAddress();
583 assert(
arrayType &&
"std::initializer_list constructed from non-array");
586 assert(record->getNumFields() == 2 &&
587 "Expected std::initializer_list to only have two fields");
590 assert(field != record->field_end() &&
591 ctx.
hasSameType(field->getType()->getPointeeType(),
593 "Expected std::initializer_list first field to be const E *");
596 AggValueSlot dest = ensureSlot(loc, e->
getType());
597 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->
getType());
599 cgf.emitLValueForFieldInitialization(destLV, *field, field->getName());
602 cgf.emitStoreThroughLValue(
RValue::get(arrayStart), start);
604 assert(field != record->field_end() &&
605 "Expected std::initializer_list to have two fields");
609 cgf.emitLValueForFieldInitialization(destLV, *field, field->getName());
612 cgf.emitStoreThroughLValue(
RValue::get(size), endOrLength);
615 assert(field->getType()->isPointerType() &&
616 ctx.
hasSameType(field->getType()->getPointeeType(),
618 "Expected std::initializer_list second field to be const E *");
620 cgf.emitStoreThroughLValue(
RValue::get(arrayEnd), endOrLength);
624 void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) {
626 "AggExprEmitter: VisitCXXScalarValueInitExpr");
628 void VisitCXXTypeidExpr(CXXTypeidExpr *e) { emitAggLoadOfLValue(e); }
629 void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e) {
632 void VisitOpaqueValueExpr(OpaqueValueExpr *e) {
634 "AggExprEmitter: VisitOpaqueValueExpr");
637 void VisitPseudoObjectExpr(PseudoObjectExpr *e) {
639 "AggExprEmitter: VisitPseudoObjectExpr");
642 void VisitVAArgExpr(VAArgExpr *e) {
645 mlir::Value vaArgValue = cgf.emitVAArg(e);
649 Address tmpAddr = cgf.createMemTemp(e->
getType(), loc,
"vaarg.tmp");
652 cgf.emitAggregateStore(vaArgValue, tmpAddr);
655 LValue tmpLValue = cgf.makeAddrLValue(tmpAddr, e->
getType());
658 emitFinalDestCopy(e->
getType(), tmpLValue);
661 void VisitCXXThrowExpr(
const CXXThrowExpr *e) { cgf.emitCXXThrowExpr(e); }
662 void VisitAtomicExpr(AtomicExpr *e) {
663 RValue result = cgf.emitAtomicExpr(e);
664 emitFinalDestCopy(e->
getType(), result);
672void AggExprEmitter::emitAggLoadOfLValue(
const Expr *e) {
681 emitFinalDestCopy(e->
getType(), lv);
684void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
688 emitAggLoadOfLValue(e);
709void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
710 QualType arrayQTy, Expr *e,
711 ArrayRef<Expr *> args, Expr *arrayFiller) {
715 const uint64_t numInitElements = args.size();
719 const QualType elementType =
724 const mlir::Type cirElementType = cgf.
convertType(elementType);
725 const cir::PointerType cirElementPtrType =
728 auto begin = cir::CastOp::create(builder, loc, cirElementPtrType,
729 cir::CastKind::array_to_ptrdecay,
732 const CharUnits elementSize =
734 const CharUnits elementAlign =
745 loc,
"arrayinit.endOfInit");
758 mlir::Value element = begin;
765 for (uint64_t i = 0; i != numInitElements; ++i) {
776 const Address address =
Address(element, cirElementType, elementAlign);
777 const LValue elementLV = cgf.
makeAddrLValue(address, elementType);
778 emitInitializationToLValue(args[i], elementLV);
781 const uint64_t numArrayElements = arrayTy.getSize();
789 if (numInitElements != numArrayElements &&
790 !(dest.
isZeroed() && hasTrivialFiller &&
793 if (numInitElements) {
795 element = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,
810 cir::ConstantOp numArrayElementsConst = builder.
getConstInt(
811 loc, mlir::cast<cir::IntType>(cgf.
ptrDiffTy), numArrayElements);
812 mlir::Value end = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,
813 begin, numArrayElementsConst);
818 [&](mlir::OpBuilder &b, mlir::Location loc) {
819 cir::LoadOp currentElement = builder.
createLoad(loc, tmpAddr);
820 cir::CmpOp cmp = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
821 currentElement, end);
825 [&](mlir::OpBuilder &b, mlir::Location loc) {
826 cir::LoadOp currentElement = builder.
createLoad(loc, tmpAddr);
830 Address(currentElement, cirElementType, elementAlign),
834 if (setArrayInitLoopExprScope)
835 idx = cir::PtrDiffOp::create(b, loc, cgf.
ptrDiffTy, currentElement,
838 CIRGenFunction::ArrayInitLoopExprScope loopExprScope(
839 cgf, setArrayInitLoopExprScope, idx);
842 emitInitializationToLValue(arrayFiller, elementLV);
844 emitNullInitializationToLValue(loc, elementLV);
848 loc, mlir::cast<cir::IntType>(cgf.
ptrDiffTy), 1);
849 auto nextElement = cir::PtrStrideOp::create(
850 builder, loc, cirElementPtrType, currentElement, one);
864void AggExprEmitter::emitFinalDestCopy(QualType
type, RValue src) {
865 assert(src.
isAggregate() &&
"value must be aggregate value!");
871void AggExprEmitter::emitFinalDestCopy(
872 QualType
type,
const LValue &src,
883 cgf.
cgm.
errorNYI(
"emitFinalDestCopy: EVK_RValue & PCK_Struct");
887 cgf.
cgm.
errorNYI(
"emitFinalDestCopy: !EVK_RValue & PCK_Struct");
898 emitCopy(
type, dest, srcAgg);
905void AggExprEmitter::emitCopy(QualType
type,
const AggValueSlot &dest,
906 const AggValueSlot &src) {
919void AggExprEmitter::emitInitializationToLValue(Expr *e, LValue lv) {
920 const QualType
type = lv.getType();
924 return emitNullInitializationToLValue(loc, lv);
930 if (
type->isReferenceType()) {
955void AggExprEmitter::VisitCXXConstructExpr(
const CXXConstructExpr *e) {
960void AggExprEmitter::emitNullInitializationToLValue(mlir::Location loc,
962 const QualType
type = lv.getType();
987void AggExprEmitter::emitComparisonResult(
const Expr *e, mlir::Location loc,
988 const ComparisonCategoryInfo &cmpInfo,
989 mlir::Value resultValue) {
998 destLVal, resultField, resultField->
getName());
1002void AggExprEmitter::VisitLambdaExpr(
LambdaExpr *e) {
1003 CIRGenFunction::SourceLocRAIIObject loc{cgf, e->
getSourceRange()};
1009 CIRGenFunction::CleanupDeactivationScope deactivationScope(cgf);
1011 for (
auto [curField, capture, captureInit] : llvm::zip(
1014 llvm::StringRef fieldName = curField->getName();
1015 if (capture.capturesVariable()) {
1016 assert(!curField->isBitField() &&
"lambdas don't have bitfield members!");
1017 ValueDecl *v = capture.getCapturedVar();
1020 }
else if (capture.capturesThis()) {
1030 if (curField->hasCapturedVLAType())
1033 emitInitializationToLValue(captureInit, lv);
1037 curField->getType().isDestructedType()) {
1038 assert(lv.isSimple());
1040 curField->getType(),
1046void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1047 CIRGenFunction::FullExprCleanupScope fullExprScope(cgf, e->
getSubExpr());
1051void AggExprEmitter::VisitCallExpr(
const CallExpr *e) {
1057 withReturnValueSlot(
1058 e, [&](ReturnValueSlot slot) {
return cgf.
emitCallExpr(e, slot); });
1061void AggExprEmitter::withReturnValueSlot(
1062 const Expr *e, llvm::function_ref<RValue(ReturnValueSlot)> fn) {
1063 QualType retTy = e->
getType();
1066 bool requiresDestruction =
1068 if (requiresDestruction)
1071 "withReturnValueSlot: return value requiring destruction is NYI");
1086 fn(ReturnValueSlot(retAddr));
1089void AggExprEmitter::VisitInitListExpr(InitListExpr *e) {
1091 llvm_unreachable(
"GNU array range designator extension");
1096 visitCXXParenListOrInitListExpr(
1100void AggExprEmitter::visitCXXParenListOrInitListExpr(
1101 Expr *e, ArrayRef<Expr *> args, FieldDecl *initializedFieldInUnion,
1102 Expr *arrayFiller) {
1105 const AggValueSlot dest = ensureSlot(loc, e->
getType());
1108 cir::ArrayType arrayTy =
1115 "visitCXXParenListOrInitListExpr variable array type");
1121 "visitCXXParenListOrInitListExpr array type");
1131 unsigned numInitElements = args.size();
1136 CIRGenFunction::CleanupDeactivationScope deactivateCleanups(cgf);
1138 unsigned curInitIndex = 0;
1141 if (
auto *cxxrd = dyn_cast<CXXRecordDecl>(record)) {
1142 assert(numInitElements >= cxxrd->getNumBases() &&
1143 "missing initializer for base class");
1144 for (
auto &base : cxxrd->bases()) {
1145 assert(!base.isVirtual() &&
"should not see vbases here");
1146 CXXRecordDecl *baseRD = base.getType()->getAsCXXRecordDecl();
1158 base.getType().isDestructedType())
1164 CIRGenFunction::FieldConstructionScope fcScope(cgf, dest.
getAddress());
1168 if (record->isUnion()) {
1171 if (!initializedFieldInUnion) {
1176 assert(llvm::all_of(record->fields(),
1177 [](
const FieldDecl *f) {
1178 return f->isUnnamedBitField() ||
1179 f->isAnonymousStructOrUnion();
1181 "Only unnamed bitfields or anonymous class allowed");
1186 FieldDecl *initedField = initializedFieldInUnion;
1189 destLV, initedField, initedField->
getName());
1191 if (numInitElements) {
1193 emitInitializationToLValue(args[0], fieldLV);
1196 emitNullInitializationToLValue(loc, fieldLV);
1203 for (
const FieldDecl *field : record->fields()) {
1205 if (field->getType()->isIncompleteArrayType())
1209 if (field->isUnnamedBitField())
1215 if (curInitIndex == numInitElements && dest.
isZeroed() &&
1223 if (curInitIndex < numInitElements) {
1225 CIRGenFunction::SourceLocRAIIObject loc{cgf, record->getSourceRange()};
1226 emitInitializationToLValue(args[curInitIndex++], lv);
1236 field->getType().isDestructedType()) {
1237 assert(lv.isSimple());
1263 getContext().getASTRecordLayout(baseRD).getSize() <=
1272 AggExprEmitter(*
this, slot).Visit(
const_cast<Expr *
>(e));
1287 assert((record->hasTrivialCopyConstructor() ||
1288 record->hasTrivialCopyAssignment() ||
1289 record->hasTrivialMoveConstructor() ||
1290 record->hasTrivialMoveAssignment() ||
1291 record->hasAttr<TrivialABIAttr>() || record->isUnion()) &&
1292 "Trying to aggregate-copy a type without a trivial copy/move "
1293 "constructor or assignment operator");
1295 if (record->isEmpty())
1318 typeInfo =
getContext().getTypeInfoDataSizeInChars(ty);
1320 typeInfo =
getContext().getTypeInfoInChars(ty);
1326 cgm.errorNYI(
"emitAggregateCopy: GC");
1332 bool skipTailPadding =
1333 mayOverlap && dataSize !=
getContext().getTypeSizeInChars(ty);
1337 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.
*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::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).
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)
CharUnits - This is an opaque type for sizes expressed in character units.
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.
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 cleanupDeactivationScope()
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...