aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CIR/CodeGen/CIRGenDecl.cpp')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenDecl.cpp98
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,