@@ -44,38 +44,70 @@ CIRGenFunction::emitAutoVarAlloca(const VarDecl &d,
4444
4545 // If the type is variably-modified, emit all the VLA sizes for it.
4646 if (ty->isVariablyModifiedType ())
47- cgm. errorNYI (d. getSourceRange (), " emitAutoVarDecl: variably modified type " );
47+ emitVariablyModifiedType (ty );
4848
4949 assert (!cir::MissingFeatures::openMP ());
5050
5151 Address address = Address::invalid ();
52- if (!ty->isConstantSizeType ())
53- cgm.errorNYI (d.getSourceRange (), " emitAutoVarDecl: non-constant size type" );
54-
55- // A normal fixed sized variable becomes an alloca in the entry block,
56- // unless:
57- // - it's an NRVO variable.
58- // - we are compiling OpenMP and it's an OpenMP local variable.
59- if (nrvo) {
60- // The named return value optimization: allocate this variable in the
61- // return slot, so that we can elide the copy when returning this
62- // variable (C++0x [class.copy]p34).
63- address = returnValue;
64-
65- if (const RecordDecl *rd = ty->getAsRecordDecl ()) {
66- if (const auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);
67- (cxxrd && !cxxrd->hasTrivialDestructor ()) ||
68- rd->isNonTrivialToPrimitiveDestroy ())
69- cgm.errorNYI (d.getSourceRange (), " emitAutoVarAlloca: set NRVO flag" );
52+ if (ty->isConstantSizeType ()) {
53+ // A normal fixed sized variable becomes an alloca in the entry block,
54+ // unless:
55+ // - it's an NRVO variable.
56+ // - we are compiling OpenMP and it's an OpenMP local variable.
57+ if (nrvo) {
58+ // The named return value optimization: allocate this variable in the
59+ // return slot, so that we can elide the copy when returning this
60+ // variable (C++0x [class.copy]p34).
61+ address = returnValue;
62+
63+ if (const RecordDecl *rd = ty->getAsRecordDecl ()) {
64+ if (const auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);
65+ (cxxrd && !cxxrd->hasTrivialDestructor ()) ||
66+ rd->isNonTrivialToPrimitiveDestroy ())
67+ cgm.errorNYI (d.getSourceRange (), " emitAutoVarAlloca: set NRVO flag" );
68+ }
69+ } else {
70+ // A normal fixed sized variable becomes an alloca in the entry block,
71+ mlir::Type allocaTy = convertTypeForMem (ty);
72+ // Create the temp alloca and declare variable using it.
73+ address = createTempAlloca (allocaTy, alignment, loc, d.getName (),
74+ /* arraySize=*/ nullptr , /* alloca=*/ nullptr , ip);
75+ declare (address.getPointer (), &d, ty, getLoc (d.getSourceRange ()),
76+ alignment);
7077 }
7178 } else {
72- // A normal fixed sized variable becomes an alloca in the entry block,
73- mlir::Type allocaTy = convertTypeForMem (ty);
74- // Create the temp alloca and declare variable using it.
75- address = createTempAlloca (allocaTy, alignment, loc, d.getName (),
76- /* arraySize=*/ nullptr , /* alloca=*/ nullptr , ip);
77- declare (address.getPointer (), &d, ty, getLoc (d.getSourceRange ()),
78- alignment);
79+ // Non-constant size type
80+ assert (!cir::MissingFeatures::openMP ());
81+ if (!didCallStackSave) {
82+ // Save the stack.
83+ cir::PointerType defaultTy = AllocaInt8PtrTy;
84+ CharUnits align = CharUnits::fromQuantity (
85+ cgm.getDataLayout ().getAlignment (defaultTy, false ));
86+ Address stack = createTempAlloca (defaultTy, align, loc, " saved_stack" );
87+
88+ mlir::Value v = builder.createStackSave (loc, defaultTy);
89+ assert (v.getType () == AllocaInt8PtrTy);
90+ builder.createStore (loc, v, stack);
91+
92+ didCallStackSave = true ;
93+
94+ // Push a cleanup block and restore the stack there.
95+ // FIXME: in general circumstances, this should be an EH cleanup.
96+ pushStackRestore (NormalCleanup, stack);
97+ }
98+
99+ VlaSizePair vlaSize = getVLASize (ty);
100+ mlir::Type memTy = convertTypeForMem (vlaSize.type );
101+
102+ // Allocate memory for the array.
103+ address =
104+ createTempAlloca (memTy, alignment, loc, d.getName (), vlaSize.numElts ,
105+ /* alloca=*/ nullptr , builder.saveInsertionPoint ());
106+
107+ // If we have debug info enabled, properly describe the VLA dimensions for
108+ // this type by registering the vla size expression for each of the
109+ // dimensions.
110+ assert (!cir::MissingFeatures::generateDebugInfo ());
79111 }
80112
81113 emission.addr = address;
@@ -696,6 +728,16 @@ struct DestroyObject final : EHScopeStack::Cleanup {
696728 cgf.emitDestroy (addr, type, destroyer);
697729 }
698730};
731+
732+ struct CallStackRestore final : EHScopeStack::Cleanup {
733+ Address stack;
734+ CallStackRestore (Address stack) : stack(stack) {}
735+ void emit (CIRGenFunction &cgf) override {
736+ mlir::Location loc = stack.getPointer ().getLoc ();
737+ mlir::Value v = cgf.getBuilder ().createLoad (loc, stack);
738+ cgf.getBuilder ().createStackRestore (loc, v);
739+ }
740+ };
699741} // namespace
700742
701743void CIRGenFunction::pushDestroy (CleanupKind cleanupKind, Address addr,
@@ -805,6 +847,10 @@ CIRGenFunction::getDestroyer(QualType::DestructionKind kind) {
805847 llvm_unreachable (" Unknown DestructionKind" );
806848}
807849
850+ void CIRGenFunction::pushStackRestore (CleanupKind kind, Address spMem) {
851+ ehStack.pushCleanup <CallStackRestore>(kind, spMem);
852+ }
853+
808854// / Enter a destroy cleanup for the given local variable.
809855void CIRGenFunction::emitAutoVarTypeCleanup (
810856 const CIRGenFunction::AutoVarEmission &emission,
0 commit comments