@@ -62,12 +62,19 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
62
62
// / Perform the final copy to DestPtr, if desired.
63
63
void emitFinalDestCopy (QualType type, const LValue &src);
64
64
65
+ void emitCopy (QualType type, const AggValueSlot &dest,
66
+ const AggValueSlot &src);
67
+
65
68
void emitInitializationToLValue (Expr *e, LValue lv);
66
69
67
70
void emitNullInitializationToLValue (mlir::Location loc, LValue lv);
68
71
69
72
void Visit (Expr *e) { StmtVisitor<AggExprEmitter>::Visit (e); }
70
73
74
+ void VisitArraySubscriptExpr (ArraySubscriptExpr *e) {
75
+ emitAggLoadOfLValue (e);
76
+ }
77
+
71
78
void VisitCallExpr (const CallExpr *e);
72
79
void VisitStmtExpr (const StmtExpr *e) {
73
80
CIRGenFunction::StmtExprEvaluation eval (cgf);
@@ -91,13 +98,6 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
91
98
}
92
99
93
100
// 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
- }
101
101
void VisitCastExpr (CastExpr *e) {
102
102
switch (e->getCastKind ()) {
103
103
case CK_LValueToRValue:
@@ -167,10 +167,6 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
167
167
cgf.cgm .errorNYI (e->getSourceRange (),
168
168
" AggExprEmitter: VisitCompoundLiteralExpr" );
169
169
}
170
- void VisitArraySubscriptExpr (ArraySubscriptExpr *e) {
171
- cgf.cgm .errorNYI (e->getSourceRange (),
172
- " AggExprEmitter: VisitArraySubscriptExpr" );
173
- }
174
170
void VisitPredefinedExpr (const PredefinedExpr *e) {
175
171
cgf.cgm .errorNYI (e->getSourceRange (),
176
172
" AggExprEmitter: VisitPredefinedExpr" );
@@ -460,7 +456,31 @@ void AggExprEmitter::emitFinalDestCopy(QualType type, const LValue &src) {
460
456
if (dest.isIgnored ())
461
457
return ;
462
458
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 ());
464
484
}
465
485
466
486
void AggExprEmitter::emitInitializationToLValue (Expr *e, LValue lv) {
@@ -712,6 +732,68 @@ void CIRGenFunction::emitAggExpr(const Expr *e, AggValueSlot slot) {
712
732
AggExprEmitter (*this , slot).Visit (const_cast <Expr *>(e));
713
733
}
714
734
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
+
715
797
LValue CIRGenFunction::emitAggExprToLValue (const Expr *e) {
716
798
assert (hasAggregateEvaluationKind (e->getType ()) && " Invalid argument!" );
717
799
Address temp = createMemTemp (e->getType (), getLoc (e->getSourceRange ()));
0 commit comments