@@ -62,12 +62,19 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
6262 // / Perform the final copy to DestPtr, if desired.
6363 void emitFinalDestCopy (QualType type, const LValue &src);
6464
65+ void emitCopy (QualType type, const AggValueSlot &dest,
66+ const AggValueSlot &src);
67+
6568 void emitInitializationToLValue (Expr *e, LValue lv);
6669
6770 void emitNullInitializationToLValue (mlir::Location loc, LValue lv);
6871
6972 void Visit (Expr *e) { StmtVisitor<AggExprEmitter>::Visit (e); }
7073
74+ void VisitArraySubscriptExpr (ArraySubscriptExpr *e) {
75+ emitAggLoadOfLValue (e);
76+ }
77+
7178 void VisitCallExpr (const CallExpr *e);
7279 void VisitStmtExpr (const StmtExpr *e) {
7380 CIRGenFunction::StmtExprEvaluation eval (cgf);
@@ -91,13 +98,6 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
9198 }
9299
93100 // Stubs -- These should be moved up when they are implemented.
94- void VisitCXXFunctionalCastExpr (CXXFunctionalCastExpr *e) {
95- // We shouldn't really get here, but we do because of missing handling for
96- // emitting constant aggregate initializers. If we just ignore this, a
97- // fallback handler will do the right thing.
98- assert (!cir::MissingFeatures::constEmitterAggILE ());
99- return ;
100- }
101101 void VisitCastExpr (CastExpr *e) {
102102 switch (e->getCastKind ()) {
103103 case CK_LValueToRValue:
@@ -167,10 +167,6 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
167167 cgf.cgm .errorNYI (e->getSourceRange (),
168168 " AggExprEmitter: VisitCompoundLiteralExpr" );
169169 }
170- void VisitArraySubscriptExpr (ArraySubscriptExpr *e) {
171- cgf.cgm .errorNYI (e->getSourceRange (),
172- " AggExprEmitter: VisitArraySubscriptExpr" );
173- }
174170 void VisitPredefinedExpr (const PredefinedExpr *e) {
175171 cgf.cgm .errorNYI (e->getSourceRange (),
176172 " AggExprEmitter: VisitPredefinedExpr" );
@@ -460,7 +456,31 @@ void AggExprEmitter::emitFinalDestCopy(QualType type, const LValue &src) {
460456 if (dest.isIgnored ())
461457 return ;
462458
463- cgf.cgm .errorNYI (" emitFinalDestCopy: non-ignored dest is NYI" );
459+ assert (!cir::MissingFeatures::aggValueSlotVolatile ());
460+ assert (!cir::MissingFeatures::aggEmitFinalDestCopyRValue ());
461+ assert (!cir::MissingFeatures::aggValueSlotGC ());
462+
463+ AggValueSlot srcAgg = AggValueSlot::forLValue (src, AggValueSlot::IsDestructed,
464+ AggValueSlot::IsAliased,
465+ AggValueSlot::MayOverlap);
466+ emitCopy (type, dest, srcAgg);
467+ }
468+
469+ // / Perform a copy from the source into the destination.
470+ // /
471+ // / \param type - the type of the aggregate being copied; qualifiers are
472+ // / ignored
473+ void AggExprEmitter::emitCopy (QualType type, const AggValueSlot &dest,
474+ const AggValueSlot &src) {
475+ assert (!cir::MissingFeatures::aggValueSlotGC ());
476+
477+ // If the result of the assignment is used, copy the LHS there also.
478+ // It's volatile if either side is. Use the minimum alignment of
479+ // the two sides.
480+ LValue destLV = cgf.makeAddrLValue (dest.getAddress (), type);
481+ LValue srcLV = cgf.makeAddrLValue (src.getAddress (), type);
482+ assert (!cir::MissingFeatures::aggValueSlotVolatile ());
483+ cgf.emitAggregateCopy (destLV, srcLV, type, dest.mayOverlap ());
464484}
465485
466486void AggExprEmitter::emitInitializationToLValue (Expr *e, LValue lv) {
@@ -712,6 +732,68 @@ void CIRGenFunction::emitAggExpr(const Expr *e, AggValueSlot slot) {
712732 AggExprEmitter (*this , slot).Visit (const_cast <Expr *>(e));
713733}
714734
735+ void CIRGenFunction::emitAggregateCopy (LValue dest, LValue src, QualType ty,
736+ AggValueSlot::Overlap_t mayOverlap) {
737+ // TODO(cir): this function needs improvements, commented code for now since
738+ // this will be touched again soon.
739+ assert (!ty->isAnyComplexType () && " Unexpected copy of complex" );
740+
741+ Address destPtr = dest.getAddress ();
742+ Address srcPtr = src.getAddress ();
743+
744+ if (getLangOpts ().CPlusPlus ) {
745+ if (auto *record = ty->getAsCXXRecordDecl ()) {
746+ assert ((record->hasTrivialCopyConstructor () ||
747+ record->hasTrivialCopyAssignment () ||
748+ record->hasTrivialMoveConstructor () ||
749+ record->hasTrivialMoveAssignment () ||
750+ record->hasAttr <TrivialABIAttr>() || record->isUnion ()) &&
751+ " Trying to aggregate-copy a type without a trivial copy/move "
752+ " constructor or assignment operator" );
753+ // Ignore empty classes in C++.
754+ if (record->isEmpty ())
755+ return ;
756+ }
757+ }
758+
759+ assert (!cir::MissingFeatures::cudaSupport ());
760+
761+ // Aggregate assignment turns into llvm.memcpy. This is almost valid per
762+ // C99 6.5.16.1p3, which states "If the value being stored in an object is
763+ // read from another object that overlaps in anyway the storage of the first
764+ // object, then the overlap shall be exact and the two objects shall have
765+ // qualified or unqualified versions of a compatible type."
766+ //
767+ // memcpy is not defined if the source and destination pointers are exactly
768+ // equal, but other compilers do this optimization, and almost every memcpy
769+ // implementation handles this case safely. If there is a libc that does not
770+ // safely handle this, we can add a target hook.
771+
772+ // Get data size info for this aggregate. Don't copy the tail padding if this
773+ // might be a potentially-overlapping subobject, since the tail padding might
774+ // be occupied by a different object. Otherwise, copying it is fine.
775+ TypeInfoChars typeInfo;
776+ if (mayOverlap)
777+ typeInfo = getContext ().getTypeInfoDataSizeInChars (ty);
778+ else
779+ typeInfo = getContext ().getTypeInfoInChars (ty);
780+
781+ assert (!cir::MissingFeatures::aggValueSlotVolatile ());
782+
783+ // NOTE(cir): original codegen would normally convert destPtr and srcPtr to
784+ // i8* since memcpy operates on bytes. We don't need that in CIR because
785+ // cir.copy will operate on any CIR pointer that points to a sized type.
786+
787+ // Don't do any of the memmove_collectable tests if GC isn't set.
788+ if (cgm.getLangOpts ().getGC () != LangOptions::NonGC)
789+ cgm.errorNYI (" emitAggregateCopy: GC" );
790+
791+ [[maybe_unused]] cir::CopyOp copyOp =
792+ builder.createCopy (destPtr.getPointer (), srcPtr.getPointer ());
793+
794+ assert (!cir::MissingFeatures::opTBAA ());
795+ }
796+
715797LValue CIRGenFunction::emitAggExprToLValue (const Expr *e) {
716798 assert (hasAggregateEvaluationKind (e->getType ()) && " Invalid argument!" );
717799 Address temp = createMemTemp (e->getType (), getLoc (e->getSourceRange ()));
0 commit comments