diff options
Diffstat (limited to 'clang/lib/CIR/CodeGen/CIRGenDecl.cpp')
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenDecl.cpp | 98 |
1 files changed, 72 insertions, 26 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp index 039d290..4a19d91 100644 --- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp @@ -44,38 +44,70 @@ CIRGenFunction::emitAutoVarAlloca(const VarDecl &d, // If the type is variably-modified, emit all the VLA sizes for it. if (ty->isVariablyModifiedType()) - cgm.errorNYI(d.getSourceRange(), "emitAutoVarDecl: variably modified type"); + emitVariablyModifiedType(ty); assert(!cir::MissingFeatures::openMP()); Address address = Address::invalid(); - if (!ty->isConstantSizeType()) - cgm.errorNYI(d.getSourceRange(), "emitAutoVarDecl: non-constant size type"); - - // A normal fixed sized variable becomes an alloca in the entry block, - // unless: - // - it's an NRVO variable. - // - we are compiling OpenMP and it's an OpenMP local variable. - if (nrvo) { - // The named return value optimization: allocate this variable in the - // return slot, so that we can elide the copy when returning this - // variable (C++0x [class.copy]p34). - address = returnValue; - - if (const RecordDecl *rd = ty->getAsRecordDecl()) { - if (const auto *cxxrd = dyn_cast<CXXRecordDecl>(rd); - (cxxrd && !cxxrd->hasTrivialDestructor()) || - rd->isNonTrivialToPrimitiveDestroy()) - cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: set NRVO flag"); + if (ty->isConstantSizeType()) { + // A normal fixed sized variable becomes an alloca in the entry block, + // unless: + // - it's an NRVO variable. + // - we are compiling OpenMP and it's an OpenMP local variable. + if (nrvo) { + // The named return value optimization: allocate this variable in the + // return slot, so that we can elide the copy when returning this + // variable (C++0x [class.copy]p34). + address = returnValue; + + if (const RecordDecl *rd = ty->getAsRecordDecl()) { + if (const auto *cxxrd = dyn_cast<CXXRecordDecl>(rd); + (cxxrd && !cxxrd->hasTrivialDestructor()) || + rd->isNonTrivialToPrimitiveDestroy()) + cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: set NRVO flag"); + } + } else { + // A normal fixed sized variable becomes an alloca in the entry block, + mlir::Type allocaTy = convertTypeForMem(ty); + // Create the temp alloca and declare variable using it. + address = createTempAlloca(allocaTy, alignment, loc, d.getName(), + /*arraySize=*/nullptr, /*alloca=*/nullptr, ip); + declare(address.getPointer(), &d, ty, getLoc(d.getSourceRange()), + alignment); } } else { - // A normal fixed sized variable becomes an alloca in the entry block, - mlir::Type allocaTy = convertTypeForMem(ty); - // Create the temp alloca and declare variable using it. - address = createTempAlloca(allocaTy, alignment, loc, d.getName(), - /*arraySize=*/nullptr, /*alloca=*/nullptr, ip); - declare(address.getPointer(), &d, ty, getLoc(d.getSourceRange()), - alignment); + // Non-constant size type + assert(!cir::MissingFeatures::openMP()); + if (!didCallStackSave) { + // Save the stack. + cir::PointerType defaultTy = AllocaInt8PtrTy; + CharUnits align = CharUnits::fromQuantity( + cgm.getDataLayout().getAlignment(defaultTy, false)); + Address stack = createTempAlloca(defaultTy, align, loc, "saved_stack"); + + mlir::Value v = builder.createStackSave(loc, defaultTy); + assert(v.getType() == AllocaInt8PtrTy); + builder.createStore(loc, v, stack); + + didCallStackSave = true; + + // Push a cleanup block and restore the stack there. + // FIXME: in general circumstances, this should be an EH cleanup. + pushStackRestore(NormalCleanup, stack); + } + + VlaSizePair vlaSize = getVLASize(ty); + mlir::Type memTy = convertTypeForMem(vlaSize.type); + + // Allocate memory for the array. + address = + createTempAlloca(memTy, alignment, loc, d.getName(), vlaSize.numElts, + /*alloca=*/nullptr, builder.saveInsertionPoint()); + + // If we have debug info enabled, properly describe the VLA dimensions for + // this type by registering the vla size expression for each of the + // dimensions. + assert(!cir::MissingFeatures::generateDebugInfo()); } emission.addr = address; @@ -696,6 +728,16 @@ struct DestroyObject final : EHScopeStack::Cleanup { cgf.emitDestroy(addr, type, destroyer); } }; + +struct CallStackRestore final : EHScopeStack::Cleanup { + Address stack; + CallStackRestore(Address stack) : stack(stack) {} + void emit(CIRGenFunction &cgf) override { + mlir::Location loc = stack.getPointer().getLoc(); + mlir::Value v = cgf.getBuilder().createLoad(loc, stack); + cgf.getBuilder().createStackRestore(loc, v); + } +}; } // namespace void CIRGenFunction::pushDestroy(CleanupKind cleanupKind, Address addr, @@ -805,6 +847,10 @@ CIRGenFunction::getDestroyer(QualType::DestructionKind kind) { llvm_unreachable("Unknown DestructionKind"); } +void CIRGenFunction::pushStackRestore(CleanupKind kind, Address spMem) { + ehStack.pushCleanup<CallStackRestore>(kind, spMem); +} + /// Enter a destroy cleanup for the given local variable. void CIRGenFunction::emitAutoVarTypeCleanup( const CIRGenFunction::AutoVarEmission &emission, |