diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -212,8 +212,8 @@ // Memory SSA operations //===----------------------------------------------------------------------===// -def fir_AllocaOp : - fir_AllocatableOp<"alloca", AutomaticAllocationScopeResource> { +def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments, + MemoryEffects<[MemAlloc]>]> { let summary = "allocate storage for a temporary on the stack given a type"; let description = [{ This primitive operation is used to allocate an object on the stack. A @@ -275,19 +275,46 @@ whether the procedure is recursive or not. }]; + let arguments = (ins + TypeAttr:$in_type, + OptionalAttr:$uniq_name, + OptionalAttr:$bindc_name, + Variadic:$typeparams, + Variadic:$shape + ); + let results = (outs fir_ReferenceType); - let verifier = allocVerify#[{ - mlir::Type outType = getType(); - if (!outType.isa()) - return emitOpError("must be a !fir.ref type"); - if (fir::isa_unknown_size_box(fir::dyn_cast_ptrEleTy(outType))) - return emitOpError("cannot allocate !fir.box of unknown rank or type"); - return mlir::success(); - }]; + let parser = + "return parseAllocatableOp(wrapAllocaResultType, parser, result);"; + let printer = "printAllocatableOp(p, (*this));"; + + let builders = [ + OpBuilder<(ins "mlir::Type":$inType, "llvm::StringRef":$uniqName, + "llvm::StringRef":$bindcName, CArg<"mlir::ValueRange", "{}">:$typeparams, + CArg<"mlir::ValueRange", "{}">:$shape, + CArg<"llvm::ArrayRef", "{}">:$attributes)>, + OpBuilder<(ins "mlir::Type":$inType, "llvm::StringRef":$uniqName, + CArg<"mlir::ValueRange", "{}">:$typeparams, + CArg<"mlir::ValueRange", "{}">:$shape, + CArg<"llvm::ArrayRef", "{}">:$attributes)>, + OpBuilder<(ins "mlir::Type":$in_type, + CArg<"mlir::ValueRange", "{}">:$typeparams, + CArg<"mlir::ValueRange", "{}">:$shape, + CArg<"llvm::ArrayRef", "{}">:$attributes)>]; - let extraClassDeclaration = extraAllocClassDeclaration#[{ - static mlir::Type wrapResultType(mlir::Type intype); + let verifier = [{ return ::verify(*this); }]; + + let extraClassDeclaration = [{ + mlir::Type getAllocatedType(); + bool hasLenParams() { return !typeparams().empty(); } + bool hasShapeOperands() { return !shape().empty(); } + unsigned numLenParams() { return typeparams().size(); } + operand_range getLenParams() { return typeparams(); } + unsigned numShapeOperands() { return shape().size(); } + operand_range getShapeOperands() { return shape(); } + static mlir::Type getRefTy(mlir::Type ty); + mlir::Type getInType() { return in_type(); } }]; } @@ -3228,9 +3255,7 @@ } /// The semantic type of the global - mlir::Type resultType() { - return fir::AllocaOp::wrapResultType(getType()); - } + mlir::Type resultType(); /// Return the initializer attribute if it exists, or a null attribute. Attribute getValueOrNull() { return initVal().getValueOr(Attribute()); } diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -60,15 +60,6 @@ return false; } -static bool verifyRecordLenParams(mlir::Type inType, unsigned numLenParams) { - if (numLenParams > 0) { - if (auto rt = inType.dyn_cast()) - return numLenParams != rt.getNumLenParams(); - return true; - } - return false; -} - static bool verifyTypeParamCount(mlir::Type inType, unsigned numParams) { auto ty = fir::unwrapSequenceType(inType); if (numParams > 0) { @@ -155,22 +146,70 @@ // AllocaOp //===----------------------------------------------------------------------===// -mlir::Type fir::AllocaOp::getAllocatedType() { - return getType().cast().getEleTy(); -} - /// Create a legal memory reference as return type -mlir::Type fir::AllocaOp::wrapResultType(mlir::Type intype) { +static mlir::Type wrapAllocaResultType(mlir::Type intype) { // FIR semantics: memory references to memory references are disallowed if (intype.isa()) return {}; return ReferenceType::get(intype); } +mlir::Type fir::AllocaOp::getAllocatedType() { + return getType().cast().getEleTy(); +} + mlir::Type fir::AllocaOp::getRefTy(mlir::Type ty) { return ReferenceType::get(ty); } +void fir::AllocaOp::build(mlir::OpBuilder &builder, + mlir::OperationState &result, mlir::Type inType, + llvm::StringRef uniqName, mlir::ValueRange typeparams, + mlir::ValueRange shape, + llvm::ArrayRef attributes) { + auto nameAttr = builder.getStringAttr(uniqName); + build(builder, result, wrapAllocaResultType(inType), inType, nameAttr, {}, + typeparams, shape); + result.addAttributes(attributes); +} + +void fir::AllocaOp::build(mlir::OpBuilder &builder, + mlir::OperationState &result, mlir::Type inType, + llvm::StringRef uniqName, llvm::StringRef bindcName, + mlir::ValueRange typeparams, mlir::ValueRange shape, + llvm::ArrayRef attributes) { + auto nameAttr = + uniqName.empty() ? mlir::StringAttr{} : builder.getStringAttr(uniqName); + auto bindcAttr = + bindcName.empty() ? mlir::StringAttr{} : builder.getStringAttr(bindcName); + build(builder, result, wrapAllocaResultType(inType), inType, nameAttr, + bindcAttr, typeparams, shape); + result.addAttributes(attributes); +} + +void fir::AllocaOp::build(mlir::OpBuilder &builder, + mlir::OperationState &result, mlir::Type inType, + mlir::ValueRange typeparams, mlir::ValueRange shape, + llvm::ArrayRef attributes) { + build(builder, result, wrapAllocaResultType(inType), inType, {}, {}, + typeparams, shape); + result.addAttributes(attributes); +} + +static mlir::LogicalResult verify(fir::AllocaOp &op) { + llvm::SmallVector visited; + if (verifyInType(op.getInType(), visited, op.numShapeOperands())) + return op.emitOpError("invalid type for allocation"); + if (verifyTypeParamCount(op.getInType(), op.numLenParams())) + return op.emitOpError("LEN params do not correspond to type"); + mlir::Type outType = op.getType(); + if (!outType.isa()) + return op.emitOpError("must be a !fir.ref type"); + if (fir::isa_unknown_size_box(fir::dyn_cast_ptrEleTy(outType))) + return op.emitOpError("cannot allocate !fir.box of unknown rank or type"); + return mlir::success(); +} + //===----------------------------------------------------------------------===// // AllocMemOp //===----------------------------------------------------------------------===//