//===-- FIROps.td - FIR operation definitions --------------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Definition of the FIR dialect operations
///
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_DIALECT_FIR_OPS
#define FORTRAN_DIALECT_FIR_OPS

include "mlir/IR/SymbolInterfaces.td"
include "mlir/Interfaces/CallInterfaces.td"
include "mlir/Interfaces/ControlFlowInterfaces.td"
include "mlir/Interfaces/LoopLikeInterface.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "flang/Optimizer/Dialect/FIRTypes.td"

// Base class for FIR operations.
// All operations automatically get a prefix of "fir.".
class fir_Op<string mnemonic, list<OpTrait> traits>
  : Op<fir_Dialect, mnemonic, traits>;

// Base class for FIR operations that take a single argument
class fir_SimpleOp<string mnemonic, list<OpTrait> traits>
  : fir_Op<mnemonic, traits> {

  let assemblyFormat = [{
    operands attr-dict `:` functional-type(operands, results)
  }];
}

// Base builder for allocate operations
def fir_AllocateOpBuilder : OpBuilder<(ins
    "mlir::Type":$inType,
    CArg<"mlir::ValueRange", "{}">:$lenParams,
    CArg<"mlir::ValueRange", "{}">:$sizes,
    CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attributes),
  [{
    $_state.addTypes(getRefTy(inType));
    $_state.addAttribute("in_type", TypeAttr::get(inType));
    $_state.addOperands(sizes);
    $_state.addAttributes(attributes);
  }]>;

def fir_NamedAllocateOpBuilder : OpBuilder<(ins
    "mlir::Type":$inType,
    "llvm::StringRef":$name,
    CArg<"mlir::ValueRange", "{}">:$lenParams,
    CArg<"mlir::ValueRange","{}">:$sizes,
    CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attributes),
  [{
    $_state.addTypes(getRefTy(inType));
    $_state.addAttribute("in_type", TypeAttr::get(inType));
    if (!name.empty())
      $_state.addAttribute("name", $_builder.getStringAttr(name));
    $_state.addOperands(sizes);
    $_state.addAttributes(attributes);
  }]>;

def fir_OneResultOpBuilder : OpBuilder<(ins
    "mlir::Type":$resultType,
    "mlir::ValueRange":$operands,
    CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attributes),
  [{
    if (resultType)
      $_state.addTypes(resultType);
    $_state.addOperands(operands);
    $_state.addAttributes(attributes);
  }]>;

// Base class of FIR operations that return 1 result
class fir_OneResultOp<string mnemonic, list<OpTrait> traits = []> :
    fir_Op<mnemonic, traits>, Results<(outs fir_Type:$res)> {
  let builders = [fir_OneResultOpBuilder];
}

// Base class of FIR operations that have 1 argument and return 1 result
class fir_SimpleOneResultOp<string mnemonic, list<OpTrait> traits = []> :
    fir_SimpleOp<mnemonic, traits> {
  let builders = [fir_OneResultOpBuilder];
}

class fir_TwoBuilders<OpBuilder b1, OpBuilder b2> {
  list<OpBuilder> builders = [b1, b2];
}

class fir_AllocatableBaseOp<string mnemonic, list<OpTrait> traits = []> :
    fir_Op<mnemonic, traits>, Results<(outs fir_Type:$res)> {
  let arguments = (ins
    OptionalAttr<StrAttr>:$name,
    OptionalAttr<BoolAttr>:$target
  );
}

class fir_AllocatableOp<string mnemonic, Resource resource,
      list<OpTrait> traits = []> :
    fir_AllocatableBaseOp<mnemonic,
	!listconcat(traits, [MemoryEffects<[MemAlloc<resource>]>])>,
    fir_TwoBuilders<fir_AllocateOpBuilder, fir_NamedAllocateOpBuilder>,
    Arguments<(ins TypeAttr:$in_type, Variadic<AnyIntegerType>:$args)> {

  let parser = [{
    mlir::Type intype;
    if (parser.parseType(intype))
      return mlir::failure();
    auto &builder = parser.getBuilder();
    result.addAttribute(inType(), mlir::TypeAttr::get(intype));
    llvm::SmallVector<mlir::OpAsmParser::OperandType, 8> operands;
    llvm::SmallVector<mlir::Type, 8> typeVec;
    bool hasOperands = false;
    if (!parser.parseOptionalLParen()) {
      // parse the LEN params of the derived type. (<params> : <types>)
      if (parser.parseOperandList(operands,
                                  mlir::OpAsmParser::Delimiter::None) ||
          parser.parseColonTypeList(typeVec) ||
          parser.parseRParen())
        return mlir::failure();
      auto lens = builder.getI32IntegerAttr(operands.size());
      result.addAttribute(lenpName(), lens);
      hasOperands = true;
    }
    if (!parser.parseOptionalComma()) {
      // parse size to scale by, vector of n dimensions of type index
      auto opSize = operands.size();
      if (parser.parseOperandList(operands, mlir::OpAsmParser::Delimiter::None))
        return mlir::failure();
      for (auto i = opSize, end = operands.size(); i != end; ++i)
        typeVec.push_back(builder.getIndexType());
      hasOperands = true;
    }
    if (hasOperands &&
        parser.resolveOperands(operands, typeVec, parser.getNameLoc(),
                               result.operands))
      return mlir::failure();
    mlir::Type restype = wrapResultType(intype);
    if (!restype) {
      parser.emitError(parser.getNameLoc(), "invalid allocate type: ")
          << intype;
      return mlir::failure();
    }
    if (parser.parseOptionalAttrDict(result.attributes) ||
        parser.addTypeToList(restype, result.types))
      return mlir::failure();
    return mlir::success();
  }];

  let printer = [{
    p << ' ' << (*this)->getAttr(inType());
    if (hasLenParams()) {
      // print the LEN parameters to a derived type in parens
      p << '(' << getLenParams() << " : " << getLenParams().getTypes() << ')';
    }
    // print the shape of the allocation (if any); all must be index type
    for (auto sh : getShapeOperands()) {
      p << ", ";
      p.printOperand(sh);
    }
    p.printOptionalAttrDict((*this)->getAttrs(), {inType(), lenpName()});
  }];

  string extraAllocClassDeclaration = [{
    static constexpr llvm::StringRef inType() { return "in_type"; }
    static constexpr llvm::StringRef lenpName() { return "len_param_count"; }
    mlir::Type getAllocatedType();

    bool hasLenParams() { return bool{(*this)->getAttr(lenpName())}; }
    bool hasShapeOperands() { return numShapeOperands() > 0; }

    unsigned numLenParams() {
      if (auto val = (*this)->getAttrOfType<mlir::IntegerAttr>(lenpName()))
        return val.getInt();
      return 0;
    }

    operand_range getLenParams() {
      return {operand_begin(), operand_begin() + numLenParams()};
    }

    unsigned numShapeOperands() {
      return operand_end() - operand_begin() + numLenParams();
    }

    operand_range getShapeOperands() {
      return {operand_begin() + numLenParams(), operand_end()};
    }

    static mlir::Type getRefTy(mlir::Type ty);

    /// Get the input type of the allocation
    mlir::Type getInType() {
      return (*this)->getAttrOfType<mlir::TypeAttr>(inType()).getValue();
    }
  }];

  // Verify checks common to all allocation operations
  string allocVerify = [{
    llvm::SmallVector<llvm::StringRef, 8> visited;
    if (verifyInType(getInType(), visited, numShapeOperands()))
      return emitOpError("invalid type for allocation");
    if (verifyRecordLenParams(getInType(), numLenParams()))
      return emitOpError("LEN params do not correspond to type");
  }];
}

//===----------------------------------------------------------------------===//
// Memory SSA operations
//===----------------------------------------------------------------------===//

def fir_AllocaOp :
      fir_AllocatableOp<"alloca", AutomaticAllocationScopeResource> {
  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
    reference to the object of type `!fir.ref<T>` is returned.  The returned
    object has an undefined/uninitialized state.  The allocation can be given
    an optional name.  The allocation may have a dynamic repetition count
    for allocating a sequence of locations for the specified type.

    ```mlir
      %c = ... : i64
      %x = fir.alloca i32
      %y = fir.alloca !fir.array<8 x i64>
      %z = fir.alloca f32, %c

      %i = ... : i16
      %j = ... : i32
      %w = fir.alloca !fir.type<PT(len1:i16, len2:i32)> (%i, %j : i16, i32)
    ```

    Note that in the case of `%z`, a contiguous block of memory is allocated
    and its size is a runtime multiple of a 32-bit REAL value.

    In the case of `%w`, the arguments `%i` and `%j` are LEN parameters
    (`len1`, `len2`) to the type `PT`.

    Finally, the operation is undefined if the ssa-value `%c` is negative.

    Fortran Semantics:
    There is no language mechanism in Fortran to allocate space on the stack
    like C's `alloca()` function. Therefore fir.alloca is not control-flow
    dependent. However, the lifetime of a stack allocation is often limited to
    a small region and a legal implementation may reuse stack storage in other
    regions when there is no conflict. For example, take the following code
    fragment.

    ```fortran
      CALL foo(1)
      CALL foo(2)
      CALL foo(3)
    ```

    A legal implementation can allocate a stack slot and initialize it with the
    constant `1`, then pass that by reference to foo. Likewise for the second
    and third calls to foo, each stack slot being initialized accordingly. It is
    also a conforming implementation to reuse the same stack slot for all three
    calls, just initializing each in turn. This is possible  as the lifetime of
    the copy of each constant need not exceed that of the CALL statement.
    Indeed, a user would likely expect a good Fortran compiler to perform such
    an optimization.

    Until Fortran 2018, procedures defaulted to non-recursive. A legal
    implementation could therefore convert stack allocations to global
    allocations. Such a conversion effectively adds the SAVE attribute to all
    variables.

    Some temporary entities (large arrays) probably should not be stack
    allocated as stack space can often be limited. A legal implementation can
    convert these large stack allocations to heap allocations regardless of
    whether the procedure is recursive or not.
  }];

  let results = (outs fir_ReferenceType);

  let verifier = allocVerify#[{
    mlir::Type outType = getType();
    if (!outType.isa<fir::ReferenceType>())
      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 extraClassDeclaration = extraAllocClassDeclaration#[{
    static mlir::Type wrapResultType(mlir::Type intype);
  }];
}

def fir_LoadOp : fir_OneResultOp<"load"> {
  let summary = "load a value from a memory reference";
  let description = [{
    Load a value from a memory reference into an ssa-value (virtual register).
    Produces an immutable ssa-value of the referent type. A memory reference
    has type `!fir.ref<T>`, `!fir.heap<T>`, or `!fir.ptr<T>`.

    ```mlir
      %a = fir.alloca i32
      %l = fir.load %a : !fir.ref<i32>
    ```

    The ssa-value has an undefined value if the memory reference is undefined
    or null.
  }];

  let arguments = (ins Arg<AnyReferenceLike, "", [MemRead]>:$memref);

  let builders = [OpBuilder<(ins "mlir::Value":$refVal),
    [{
      if (!refVal) {
        mlir::emitError($_state.location, "LoadOp has null argument");
        return;
      }
      auto eleTy = fir::dyn_cast_ptrEleTy(refVal.getType());
      if (!eleTy) {
        mlir::emitError($_state.location, "not a memory reference type");
        return;
      }
      $_state.addOperands(refVal);
      $_state.addTypes(eleTy);
    }]
  >];

  let parser = [{
    mlir::Type type;
    mlir::OpAsmParser::OperandType oper;
    if (parser.parseOperand(oper) ||
        parser.parseOptionalAttrDict(result.attributes) ||
        parser.parseColonType(type) ||
        parser.resolveOperand(oper, type, result.operands))
       return mlir::failure();
    mlir::Type eleTy;
    if (getElementOf(eleTy, type) ||
        parser.addTypeToList(eleTy, result.types))
       return mlir::failure();
    return mlir::success();
  }];

  let printer = [{
    p << ' ';
    p.printOperand(memref());
    p.printOptionalAttrDict((*this)->getAttrs(), {});
    p << " : " << memref().getType();
  }];

  let extraClassDeclaration = [{
    static mlir::ParseResult getElementOf(mlir::Type &ele, mlir::Type ref);
  }];
}

def fir_SaveResultOp : fir_Op<"save_result", [AttrSizedOperandSegments]> {
  let summary = [{
    save an array, box, or record function result SSA-value to a memory location
  }];

  let description = [{
    Save the result of a function returning an array, box, or record type value
    into a memory location given the shape and length parameters of the result.

    Function results of type fir.box, fir.array, or fir.rec are abstract values
    that require a storage to be manipulated on the caller side. This operation
    allows associating such abstract result to a storage. In later lowering of
    the function interfaces, this storage might be used to pass the result in
    memory.

    For arrays, result, it is required to provide the shape of the result. For
    character arrays and derived types with length parameters, the length
    parameter values must be provided.

    The fir.save_result associated to a function call must immediately follow
    the call and be in the same block.

    ```mlir
      %buffer = fir.alloca fir.array<?xf32>, %c100
      %shape = fir.shape %c100
      %array_result = fir.call @foo() : () -> fir.array<?xf32>
      fir.save_result %array_result to %buffer(%shape)
      %coor = fir.array_coor %buffer%(%shape), %c5
      %fifth_element = fir.load %coor : f32
    ```

    The above fir.save_result allows saving a fir.array function result into
    a buffer to later access its 5th element.

  }];

  let arguments = (ins ArrayOrBoxOrRecord:$value,
                   Arg<AnyReferenceLike, "", [MemWrite]>:$memref,
                   Optional<AnyShapeType>:$shape,
                   Variadic<AnyIntegerType>:$typeparams);

  let assemblyFormat = [{
    $value `to` $memref (`(` $shape^ `)`)? (`typeparams` $typeparams^)?
    attr-dict `:` type(operands)
  }];

  let verifier = [{ return ::verify(*this); }];
}

def fir_StoreOp : fir_Op<"store", []> {
  let summary = "store an SSA-value to a memory location";

  let description = [{
    Store an ssa-value (virtual register) to a memory reference.  The stored
    value must be of the same type as the referent type of the memory
    reference.

    ```mlir
      %v = ... : f64
      %p = ... : !fir.ptr<f64>
      fir.store %v to %p : !fir.ptr<f64>
    ```

    The above store changes the value to which the pointer is pointing and not
    the pointer itself. The operation is undefined if the memory reference,
    `%p`, is undefined or null.
  }];

  let arguments = (ins AnyType:$value,
                   Arg<AnyReferenceLike, "", [MemWrite]>:$memref);

  let parser = [{
    mlir::Type type;
    mlir::OpAsmParser::OperandType oper;
    mlir::OpAsmParser::OperandType store;
    if (parser.parseOperand(oper) ||
        parser.parseKeyword("to") ||
        parser.parseOperand(store) ||
        parser.parseOptionalAttrDict(result.attributes) ||
        parser.parseColonType(type) ||
        parser.resolveOperand(oper, elementType(type),
          result.operands) ||
        parser.resolveOperand(store, type, result.operands))
       return mlir::failure();
    return mlir::success();
  }];

  let printer = [{
    p << ' ';
    p.printOperand(value());
    p << " to ";
    p.printOperand(memref());
    p.printOptionalAttrDict((*this)->getAttrs(), {});
    p << " : " << memref().getType();
  }];

  let verifier = [{
    if (value().getType() != fir::dyn_cast_ptrEleTy(memref().getType()))
      return emitOpError("store value type must match memory reference type");
    if (fir::isa_unknown_size_box(value().getType()))
      return emitOpError("cannot store !fir.box of unknown rank or type");
    return mlir::success();
  }];

  let extraClassDeclaration = [{
    static mlir::Type elementType(mlir::Type refType);
  }];
}

def fir_UndefOp : fir_OneResultOp<"undefined", [NoSideEffect]> {
  let summary = "explicit undefined value of some type";
  let description = [{
    Constructs an ssa-value of the specified type with an undefined value.
    This operation is typically created internally by the mem2reg conversion
    pass. An undefined value can be of any type except `!fir.ref<T>`.

    ```mlir
      %a = fir.undefined !fir.array<10 x !fir.type<T>>
    ```

    The example creates an array shaped ssa value. The array is rank 1, extent
    10, and each element has type `!fir.type<T>`.
  }];

  let results = (outs AnyType:$intype);

  let assemblyFormat = "type($intype) attr-dict";

  let verifier = [{
    // allow `undef : ref<T>` since it is a possible from transformations
    return mlir::success();
  }];
}

def fir_ZeroOp : fir_OneResultOp<"zero_bits", [NoSideEffect]> {
  let summary = "explicit polymorphic zero value of some type";
  let description = [{
    Constructs an ssa-value of the specified type with a value of zero for all
    bits.

    ```mlir
      %a = fir.zero_bits !fir.box<!fir.array<10 x !fir.type<T>>>
    ```

    The example creates a value of type box where all bits are zero.
  }];

  let results = (outs AnyType:$intype);

  let assemblyFormat = "type($intype) attr-dict";
}

def fir_AllocMemOp : fir_AllocatableOp<"allocmem", DefaultResource> {
  let summary = "allocate storage on the heap for an object of a given type";

  let description = [{
    Creates a heap memory reference suitable for storing a value of the
    given type, T.  The heap refernce returned has type `!fir.heap<T>`.
    The memory object is in an undefined state.  `allocmem` operations must
    be paired with `freemem` operations to avoid memory leaks.

    ```mlir
      %0 = fir.allocmem !fir.array<10 x f32>
      fir.freemem %0 : !fir.heap<!fir.array<10 x f32>>
    ```
  }];

  let results = (outs fir_HeapType);

  let verifier = allocVerify#[{
    mlir::Type outType = getType();
    if (!outType.dyn_cast<fir::HeapType>())
      return emitOpError("must be a !fir.heap 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 extraClassDeclaration = extraAllocClassDeclaration#[{
    static mlir::Type wrapResultType(mlir::Type intype);
  }];
}

def fir_FreeMemOp : fir_Op<"freemem", [MemoryEffects<[MemFree]>]> {
  let summary = "free a heap object";

  let description = [{
    Deallocates a heap memory reference that was allocated by an `allocmem`.
    The memory object that is deallocated is placed in an undefined state
    after `fir.freemem`.  Optimizations may treat the loading of an object
    in the undefined state as undefined behavior.  This includes aliasing
    references, such as the result of an `fir.embox`.

    ```mlir
      %21 = fir.allocmem !fir.type<ZT(p:i32){field:i32}>
      ...
      fir.freemem %21 : !fir.heap<!fir.type<ZT>>
    ```
  }];

  let arguments = (ins Arg<fir_HeapType, "", [MemFree]>:$heapref);

  let assemblyFormat = "$heapref attr-dict `:` type($heapref)";
}

//===----------------------------------------------------------------------===//
// Terminator operations
//===----------------------------------------------------------------------===//

class fir_SwitchTerminatorOp<string mnemonic, list<OpTrait> traits = []> :
    fir_Op<mnemonic, !listconcat(traits, [AttrSizedOperandSegments,
    DeclareOpInterfaceMethods<BranchOpInterface>, Terminator])> {

  let arguments = (ins
    AnyType:$selector,
    Variadic<AnyType>:$compareArgs,
    Variadic<AnyType>:$targetArgs
  );

  let results = (outs);

  let successors = (successor VariadicSuccessor<AnySuccessor>:$targets);

  string extraSwitchClassDeclaration = [{
    using Conditions = mlir::Value;

    static constexpr llvm::StringRef getCasesAttr() { return "case_tags"; }

    // The number of destination conditions that may be tested
    unsigned getNumConditions() {
      return (*this)->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).size();
    }

    // The selector is the value being tested to determine the destination
    mlir::Value getSelector() { return selector(); }
    mlir::Value getSelector(llvm::ArrayRef<mlir::Value> operands) {
      return operands[0];
    }

    // The number of blocks that may be branched to
    unsigned getNumDest() { return (*this)->getNumSuccessors(); }

    llvm::Optional<mlir::OperandRange> getCompareOperands(unsigned cond);
    llvm::Optional<llvm::ArrayRef<mlir::Value>> getCompareOperands(
        llvm::ArrayRef<mlir::Value> operands, unsigned cond);

    llvm::Optional<llvm::ArrayRef<mlir::Value>> getSuccessorOperands(
        llvm::ArrayRef<mlir::Value> operands, unsigned cond);
    using BranchOpInterfaceTrait::getSuccessorOperands;

    // Helper function to deal with Optional operand forms
    void printSuccessorAtIndex(mlir::OpAsmPrinter &p, unsigned i) {
      auto *succ = getSuccessor(i);
      auto ops = getSuccessorOperands(i);
      if (ops.hasValue())
        p.printSuccessorAndUseList(succ, ops.getValue());
      else
        p.printSuccessor(succ);
    }

    unsigned targetOffsetSize();
  }];
}

class fir_IntegralSwitchTerminatorOp<string mnemonic,
    list<OpTrait> traits = []> : fir_SwitchTerminatorOp<mnemonic, traits> {

  let skipDefaultBuilders = 1;
  let builders = [OpBuilder<(ins "mlir::Value":$selector,
    "llvm::ArrayRef<int64_t>":$compareOperands,
    "llvm::ArrayRef<mlir::Block *>":$destinations,
    CArg<"llvm::ArrayRef<mlir::ValueRange>", "{}">:$destOperands,
    CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attributes),
    [{
      $_state.addOperands(selector);
      llvm::SmallVector<mlir::Attribute, 8> ivalues;
      for (auto iv : compareOperands)
        ivalues.push_back($_builder.getI64IntegerAttr(iv));
      ivalues.push_back($_builder.getUnitAttr());
      $_state.addAttribute(getCasesAttr(), $_builder.getArrayAttr(ivalues));
      const auto count = destinations.size();
      for (auto d : destinations)
        $_state.addSuccessors(d);
      const auto opCount = destOperands.size();
      llvm::SmallVector<int32_t, 8> argOffs;
      int32_t sumArgs = 0;
      for (std::remove_const_t<decltype(count)> i = 0; i != count; ++i) {
        if (i < opCount) {
          $_state.addOperands(destOperands[i]);
          const auto argSz = destOperands[i].size();
          argOffs.push_back(argSz);
          sumArgs += argSz;
        } else {
          argOffs.push_back(0);
        }
      }
      $_state.addAttribute(getOperandSegmentSizeAttr(),
        $_builder.getI32VectorAttr({1, 0, sumArgs}));
      $_state.addAttribute(getTargetOffsetAttr(),
        $_builder.getI32VectorAttr(argOffs));
      $_state.addAttributes(attributes);
    }]
  >];

  let parser = [{
    mlir::OpAsmParser::OperandType selector;
    mlir::Type type;
    if (parseSelector(parser, result, selector, type))
      return mlir::failure();

    llvm::SmallVector<mlir::Attribute, 8> ivalues;
    llvm::SmallVector<mlir::Block *, 8> dests;
    llvm::SmallVector<llvm::SmallVector<mlir::Value, 8>, 8> destArgs;
    while (true) {
      mlir::Attribute ivalue; // Integer or Unit
      mlir::Block *dest;
      llvm::SmallVector<mlir::Value, 8> destArg;
      mlir::NamedAttrList temp;
      if (parser.parseAttribute(ivalue, "i", temp) ||
          parser.parseComma() ||
          parser.parseSuccessorAndUseList(dest, destArg))
        return mlir::failure();
      ivalues.push_back(ivalue);
      dests.push_back(dest);
      destArgs.push_back(destArg);
      if (!parser.parseOptionalRSquare())
        break;
      if (parser.parseComma())
        return mlir::failure();
    }
    auto &bld = parser.getBuilder();
    result.addAttribute(getCasesAttr(), bld.getArrayAttr(ivalues));
    llvm::SmallVector<int32_t, 8> argOffs;
    int32_t sumArgs = 0;
    const auto count = dests.size();
    for (std::remove_const_t<decltype(count)> i = 0; i != count; ++i) {
      result.addSuccessors(dests[i]);
      result.addOperands(destArgs[i]);
      auto argSize = destArgs[i].size();
      argOffs.push_back(argSize);
      sumArgs += argSize;
    }
    result.addAttribute(getOperandSegmentSizeAttr(),
                        bld.getI32VectorAttr({1, 0, sumArgs}));
    result.addAttribute(getTargetOffsetAttr(), bld.getI32VectorAttr(argOffs));
    return mlir::success();
  }];

  let printer = [{
    p << ' ';
    p.printOperand(getSelector());
    p << " : " << getSelector().getType() << " [";
    auto cases = (*this)->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).getValue();
    auto count = getNumConditions();
    for (decltype(count) i = 0; i != count; ++i) {
      if (i)
        p << ", ";
      auto &attr = cases[i];
      if (auto intAttr = attr.dyn_cast_or_null<mlir::IntegerAttr>())
        p << intAttr.getValue();
      else
        p.printAttribute(attr);
      p << ", ";
      printSuccessorAtIndex(p, i);
    }
    p << ']';
    p.printOptionalAttrDict((*this)->getAttrs(), {getCasesAttr(), getCompareOffsetAttr(),
        getTargetOffsetAttr(), getOperandSegmentSizeAttr()});
  }];

  let verifier = [{
    if (!(getSelector().getType().isa<mlir::IntegerType>() ||
          getSelector().getType().isa<mlir::IndexType>() ||
          getSelector().getType().isa<fir::IntegerType>()))
      return emitOpError("must be an integer");
    auto cases = (*this)->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).getValue();
    auto count = getNumDest();
    if (count == 0)
      return emitOpError("must have at least one successor");
    if (getNumConditions() != count)
      return emitOpError("number of cases and targets don't match");
    if (targetOffsetSize() != count)
      return emitOpError("incorrect number of successor operand groups");
    for (decltype(count) i = 0; i != count; ++i) {
      auto &attr = cases[i];
      if (!(attr.isa<mlir::IntegerAttr>() || attr.isa<mlir::UnitAttr>()))
        return emitOpError("invalid case alternative");
    }
    return mlir::success();
  }];

  let extraClassDeclaration = extraSwitchClassDeclaration;
}

def fir_SelectOp : fir_IntegralSwitchTerminatorOp<"select"> {
  let summary = "a multiway branch";

  let description = [{
    A multiway branch terminator with similar semantics to C's `switch`
    statement.  A selector value is matched against a list of constants
    of the same type for a match.  When a match is found, control is
    transferred to the corresponding basic block.  A `select` must have
    at least one basic block with a corresponding `unit` match, and
    that block will be selected when all other conditions fail to match.

    ```mlir
      fir.select %arg:i32 [1, ^bb1(%0 : i32),
                           2, ^bb2(%2,%arg,%arg2 : i32,i32,i32),
                          -3, ^bb3(%arg2,%2 : i32,i32),
                           4, ^bb4(%1 : i32),
                        unit, ^bb5]
    ```
  }];
}

def fir_SelectRankOp : fir_IntegralSwitchTerminatorOp<"select_rank"> {
  let summary = "Fortran's SELECT RANK statement";

  let description = [{
    Similar to `select`, `select_rank` provides a way to express Fortran's
    SELECT RANK construct.  In this case, the rank of the selector value
    is matched against constants of integer type.  The structure is the
    same as `select`, but `select_rank` determines the rank of the selector
    variable at runtime to determine the best match.

    ```mlir
      fir.select_rank %arg:i32 [1, ^bb1(%0 : i32),
                                2, ^bb2(%2,%arg,%arg2 : i32,i32,i32),
                                3, ^bb3(%arg2,%2 : i32,i32),
                               -1, ^bb4(%1 : i32),
                             unit, ^bb5]
    ```
  }];
}

def fir_SelectCaseOp : fir_SwitchTerminatorOp<"select_case"> {
  let summary = "Fortran's SELECT CASE statement";

  let description = [{
    Similar to `select`, `select_case` provides a way to express Fortran's
    SELECT CASE construct.  In this case, the selector value is matched
    against variables (not just constants) and ranges.  The structure is
    the same as `select`, but `select_case` allows for the expression of
    more complex match conditions.

    ```mlir
      fir.select_case %arg : i32 [
            #fir.point, %0, ^bb1(%0 : i32),
            #fir.lower, %1, ^bb2(%2,%arg,%arg2,%1 : i32,i32,i32,i32),
            #fir.interval, %2, %3, ^bb3(%2,%arg2 : i32,i32),
            #fir.upper, %arg, ^bb4(%1 : i32),
            unit, ^bb5]
    ```
  }];

  let skipDefaultBuilders = 1;
  let builders = [
    OpBuilder<(ins "mlir::Value":$selector,
      "llvm::ArrayRef<mlir::Attribute>":$compareAttrs,
      "llvm::ArrayRef<mlir::ValueRange>":$cmpOperands,
      "llvm::ArrayRef<mlir::Block *>":$destinations,
      CArg<"llvm::ArrayRef<mlir::ValueRange>", "{}">:$destOperands,
      CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attributes)>,
    OpBuilder<(ins "mlir::Value":$selector,
      "llvm::ArrayRef<mlir::Attribute>":$compareAttrs,
      "llvm::ArrayRef<mlir::Value>":$cmpOpList,
      "llvm::ArrayRef<mlir::Block *>":$destinations,
      CArg<"llvm::ArrayRef<mlir::ValueRange>", "{}">:$destOperands,
      CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attributes)>];

  let parser = "return parseSelectCase(parser, result);";

  let printer = [{
    p << ' ';
    p.printOperand(getSelector());
    p << " : " << getSelector().getType() << " [";
    auto cases = (*this)->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).getValue();
    auto count = getNumConditions();
    for (decltype(count) i = 0; i != count; ++i) {
      if (i)
        p << ", ";
      p << cases[i] << ", ";
      if (!cases[i].isa<mlir::UnitAttr>()) {
        auto caseArgs = *getCompareOperands(i);
        p.printOperand(*caseArgs.begin());
        p << ", ";
        if (cases[i].isa<fir::ClosedIntervalAttr>()) {
          p.printOperand(*(++caseArgs.begin()));
          p << ", ";
        }
      }
      printSuccessorAtIndex(p, i);
    }
    p << ']';
    p.printOptionalAttrDict((*this)->getAttrs(), {getCasesAttr(), getCompareOffsetAttr(),
        getTargetOffsetAttr(), getOperandSegmentSizeAttr()});
  }];

  let verifier = [{
    if (!(getSelector().getType().isa<mlir::IntegerType>() ||
          getSelector().getType().isa<mlir::IndexType>() ||
          getSelector().getType().isa<fir::IntegerType>() ||
          getSelector().getType().isa<fir::LogicalType>() ||
          getSelector().getType().isa<fir::CharacterType>()))
      return emitOpError("must be an integer, character, or logical");
    auto cases = (*this)->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).getValue();
    auto count = getNumDest();
    if (count == 0)
      return emitOpError("must have at least one successor");
    if (getNumConditions() != count)
      return emitOpError("number of conditions and successors don't match");
    if (compareOffsetSize() != count)
      return emitOpError("incorrect number of compare operand groups");
    if (targetOffsetSize() != count)
      return emitOpError("incorrect number of successor operand groups");
    for (decltype(count) i = 0; i != count; ++i) {
      auto &attr = cases[i];
      if (!(attr.isa<fir::PointIntervalAttr>() ||
            attr.isa<fir::LowerBoundAttr>() ||
            attr.isa<fir::UpperBoundAttr>() ||
            attr.isa<fir::ClosedIntervalAttr>() ||
            attr.isa<mlir::UnitAttr>()))
        return emitOpError("incorrect select case attribute type");
    }
    return mlir::success();
  }];

  let extraClassDeclaration = extraSwitchClassDeclaration#[{
    unsigned compareOffsetSize();
  }];
}

def fir_SelectTypeOp : fir_SwitchTerminatorOp<"select_type"> {
  let summary = "Fortran's SELECT TYPE statement";

  let description = [{
    Similar to `select`, `select_type` provides a way to express Fortran's
    SELECT TYPE construct.  In this case, the type of the selector value
    is matched against a list of type descriptors.  The structure is the
    same as `select`, but `select_type` determines the type of the selector
    variable at runtime to determine the best match.

    ```mlir
      fir.select_type %arg : !fir.box<()> [
          #fir.instance<!fir.type<type1>>, ^bb1(%0 : i32),
          #fir.instance<!fir.type<type2>>, ^bb2(%2 : i32),
          #fir.subsumed<!fir.type<type3>>, ^bb3(%2 : i32),
          #fir.instance<!fir.type<type4>>, ^bb4(%1,%3 : i32,f32),
          unit, ^bb5]
    ```
  }];

  let skipDefaultBuilders = 1;
  let builders = [OpBuilder<(ins "mlir::Value":$selector,
    "llvm::ArrayRef<mlir::Attribute>":$typeOperands,
    "llvm::ArrayRef<mlir::Block *>":$destinations,
    CArg<"llvm::ArrayRef<mlir::ValueRange>", "{}">:$destOperands,
    CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attributes),
    [{
      $_state.addOperands(selector);
      $_state.addAttribute(getCasesAttr(),
        $_builder.getArrayAttr(typeOperands));
      const auto count = destinations.size();
      for (auto d : destinations)
        $_state.addSuccessors(d);
      const auto opCount = destOperands.size();
      llvm::SmallVector<int32_t, 8> argOffs;
      int32_t sumArgs = 0;
      for (std::remove_const_t<decltype(count)> i = 0; i != count; ++i) {
        if (i < opCount) {
          $_state.addOperands(destOperands[i]);
          const auto argSz = destOperands[i].size();
          argOffs.push_back(argSz);
          sumArgs += argSz;
        } else {
          argOffs.push_back(0);
        }
      }
      $_state.addAttribute(getOperandSegmentSizeAttr(),
        $_builder.getI32VectorAttr({1, 0, sumArgs}));
      $_state.addAttribute(getTargetOffsetAttr(),
        $_builder.getI32VectorAttr(argOffs));
      $_state.addAttributes(attributes);
    }]
  >];

  let parser = "return parseSelectType(parser, result);";

  let printer = [{
    p << ' ';
    p.printOperand(getSelector());
    p << " : " << getSelector().getType() << " [";
    auto cases = (*this)->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).getValue();
    auto count = getNumConditions();
    for (decltype(count) i = 0; i != count; ++i) {
      if (i)
        p << ", ";
      p << cases[i] << ", ";
      printSuccessorAtIndex(p, i);
    }
    p << ']';
    p.printOptionalAttrDict((*this)->getAttrs(), {getCasesAttr(), getCompareOffsetAttr(),
        getTargetOffsetAttr(), getOperandSegmentSizeAttr()});
  }];

  let verifier = [{
    if (!(getSelector().getType().isa<fir::BoxType>()))
      return emitOpError("must be a boxed type");
    auto cases = (*this)->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).getValue();
    auto count = getNumDest();
    if (count == 0)
      return emitOpError("must have at least one successor");
    if (getNumConditions() != count)
      return emitOpError("number of conditions and successors don't match");
    if (targetOffsetSize() != count)
      return emitOpError("incorrect number of successor operand groups");
    for (decltype(count) i = 0; i != count; ++i) {
      auto &attr = cases[i];
      if (!(attr.isa<fir::ExactTypeAttr>() || attr.isa<fir::SubclassAttr>() ||
            attr.isa<mlir::UnitAttr>()))
        return emitOpError("invalid type-case alternative");
    }
    return mlir::success();
  }];

  let extraClassDeclaration = extraSwitchClassDeclaration;
}

def fir_UnreachableOp : fir_Op<"unreachable", [Terminator]> {
  let summary = "the unreachable instruction";

  let description = [{
    Terminates a basic block with the assertion that the end of the block
    will never be reached at runtime.  This instruction can be used
    immediately after a call to the Fortran runtime to terminate the
    program, for example.  This instruction corresponds to the LLVM IR
    instruction `unreachable`.

    ```mlir
      fir.unreachable
    ```
  }];

  let parser = "return mlir::success();";

  let printer = "";
}

def fir_FirEndOp : fir_Op<"end", [Terminator]> {
  let summary = "the end instruction";

  let description = [{
    The end terminator is a special terminator used inside various FIR
    operations that have regions.  End is thus the custom invisible terminator
    for these operations.  It is implicit and need not appear in the textual
    representation.
  }];
}

def fir_HasValueOp : fir_Op<"has_value", [Terminator, HasParent<"GlobalOp">]> {
  let summary = "terminator for GlobalOp";
  let description = [{
    The terminator for a GlobalOp with a body.

    ```mlir
      global @variable : tuple<i32, f32> {
        %0 = constant 45 : i32
        %1 = constant 100.0 : f32
        %2 = fir.undefined tuple<i32, f32>
        %3 = constant 0 : index
        %4 = fir.insert_value %2, %0, %3 : (tuple<i32, f32>, i32, index) -> tuple<i32, f32>
        %5 = constant 1 : index
        %6 = fir.insert_value %4, %1, %5 : (tuple<i32, f32>, f32, index) -> tuple<i32, f32>
        fir.has_value %6 : tuple<i32, f32>
      }
    ```
  }];

  let arguments = (ins AnyType:$resval);

  let assemblyFormat = "$resval attr-dict `:` type($resval)";
}

//===------------------------------------------------------------------------===//
// Operations on !fir.box<T> type objects
//===------------------------------------------------------------------------===//

def fir_EmboxOp : fir_Op<"embox", [NoSideEffect, AttrSizedOperandSegments]> {
  let summary = "boxes a given reference and (optional) dimension information";

  let description = [{
    Create a boxed reference value. In Fortran, the implementation can require
    extra information about an entity, such as its type, rank, etc.  This
    auxilliary information is packaged and abstracted as a value with box type
    by the calling routine. (In Fortran, these are called descriptors.)

    ```mlir
      %c1 = constant 1 : index
      %c10 = constant 10 : index
      %5 = ... : !fir.ref<!fir.array<10 x i32>>
      %6 = fir.embox %5 : (!fir.ref<!fir.array<10 x i32>>) -> !fir.box<!fir.array<10 x i32>>
    ```

    The descriptor tuple may contain additional implementation-specific
    information through the use of additional attributes.
    Specifically,
        - shape: emboxing an array may require shape information (an array's
          lower bounds and extents may not be known until runtime),
        - slice: an array section can be described with a slice triple,
        - typeparams: for emboxing a derived type with LEN type parameters,
        - accessMap: unused/experimental.
  }];

  let arguments = (ins
    AnyReferenceLike:$memref,
    Optional<AnyShapeType>:$shape,
    Optional<fir_SliceType>:$slice,
    Variadic<AnyIntegerType>:$typeparams,
    OptionalAttr<AffineMapAttr>:$accessMap
  );

  let results = (outs fir_BoxType);

  let builders = [
    OpBuilder<(ins "llvm::ArrayRef<mlir::Type>":$resultTypes,
      "mlir::Value":$memref, CArg<"mlir::Value", "{}">:$shape,
      CArg<"mlir::Value", "{}">:$slice,
      CArg<"mlir::ValueRange", "{}">:$lenParams),
    [{ return build($_builder, $_state, resultTypes, memref, shape, slice,
                    lenParams, mlir::AffineMapAttr{}); }]>
  ];

  let assemblyFormat = [{
    $memref (`(` $shape^ `)`)? (`[` $slice^ `]`)? (`typeparams` $typeparams^)?
      (`map` $accessMap^)? attr-dict `:` functional-type(operands, results)
  }];

  let verifier = [{ return ::verify(*this); }];

  let extraClassDeclaration = [{
    mlir::Value getShape() { return shape(); }
    mlir::Value getSlice() { return slice(); }
    bool hasLenParams() { return !typeparams().empty(); }
    unsigned numLenParams() { return typeparams().size(); }
  }];
}

def fir_ReboxOp : fir_Op<"rebox", [NoSideEffect, AttrSizedOperandSegments]> {
  let summary = "create a box given another box and (optional) dimension information";

  let description = [{
    Create a new boxed reference value from another box. This is meant to be used
    when the taking a reference to part of a boxed value, or to an entire boxed value with
    new shape or type information.

    The new extra information can be:
      - new shape information (new lower bounds, new rank, or new extents.
        New rank/extents can only be provided if the original fir.box is
        contiguous in all dimension but maybe the first one). The shape
        operand must be provided to set new shape information.
      - new type (only for derived types). It is possible to set the dynamic type
        of the new box to one of the parent types of the input box dynamic type.
        Type parameters cannot be changed. This change is reflected in the requested
        result type of the new box.

    A slice argument can be provided to build a reference to part of a boxed value.
    In this case, the shape operand must be absent or be a fir.shift that can be
    used to provide a non default origin for the slice.

    The following example illustrates creating a fir.box for x(10:33:2)
    where x is described by a fir.box and has non default lower bounds,
    and then applying a new 2-dimension shape to this fir.box.

    ```mlir
      %0 = fir.slice %c10, %c33, %c2 : (index, index, index) -> !fir.slice<1>
      %1 = fir.shift %c0 : (index) -> !fir.shift<1>
      %2 = fir.rebox %x(%1) [%0] : (!fir.box<!fir.array<?xf32>>, !fir.shift<1>, !fir.slice<1>) -> !fir.box<!fir.array<?xf32>>
      %3 = fir.shape %c3, %c4 : (index, index) -> !fir.shape<2>
      %4 = fir.rebox %2(%3) : (!fir.box<!fir.array<?xf32>>, !fir.shape<2>) -> !fir.box<!fir.array<?x?xf32>>
    ```

  }];

  let arguments = (ins
    fir_BoxType:$box,
    Optional<AnyShapeOrShiftType>:$shape,
    Optional<fir_SliceType>:$slice
  );

  let results = (outs fir_BoxType);

  let assemblyFormat = [{
    $box (`(` $shape^ `)`)? (`[` $slice^ `]`)? attr-dict `:` functional-type(operands, results)
  }];

  let verifier = [{ return ::verify(*this); }];
}

def fir_EmboxCharOp : fir_Op<"emboxchar", [NoSideEffect]> {
  let summary = "boxes a given CHARACTER reference and its LEN parameter";

  let description = [{
    Create a boxed CHARACTER value. The CHARACTER type has the LEN type
    parameter, the value of which may only be known at runtime.  Therefore,
    a variable of type CHARACTER has both its data reference as well as a
    LEN type parameter.

    ```fortran
      CHARACTER(LEN=10) :: var
    ```
    ```mlir
      %4 = ...         : !fir.ref<!fir.array<10 x !fir.char<1>>>
      %5 = constant 10 : i32
      %6 = fir.emboxchar %4, %5 : (!fir.ref<!fir.array<10 x !fir.char<1>>>, i32) -> !fir.boxchar<1>
    ```

    In the above `%4` is a memory reference to a buffer of 10 CHARACTER units.
    This buffer and its LEN value (10) are wrapped into a pair in `%6`.
  }];

  let arguments = (ins AnyReferenceLike:$memref, AnyIntegerLike:$len);

  let results = (outs fir_BoxCharType);

  let assemblyFormat = [{
    $memref `,` $len attr-dict `:` functional-type(operands, results)
  }];

  let verifier = [{
    auto eleTy = elementTypeOf(memref().getType());
    if (!eleTy.dyn_cast<CharacterType>())
      return mlir::failure();
    return mlir::success();
  }];
}

def fir_EmboxProcOp : fir_Op<"emboxproc", [NoSideEffect]> {
  let summary = "boxes a given procedure and optional host context";

  let description = [{
    Creates an abstract encapsulation of a PROCEDURE POINTER along with an
    optional pointer to a host instance context. If the pointer is not to an
    internal procedure or the internal procedure does not need a host context
    then the form takes only the procedure's symbol.

    ```mlir
      %0 = fir.emboxproc @f : ((i32) -> i32) -> !fir.boxproc<(i32) -> i32>
    ```

    An internal procedure requiring a host instance for correct execution uses
    the second form. The closure of the host procedure's state is passed as a
    reference to a tuple. It is the responsibility of the host to manage the
    context's values accordingly, up to and including inhibiting register
    promotion of local values.

    ```mlir
      %4 = ... : !fir.ref<tuple<i32, i32>>
      %5 = fir.emboxproc @g, %4 : ((i32) -> i32, !fir.ref<tuple<i32, i32>>) -> !fir.boxproc<(i32) -> i32>
    ```
  }];

  let arguments = (ins SymbolRefAttr:$funcname, AnyReferenceLike:$host);

  let results = (outs fir_BoxProcType);

  let parser = [{
    mlir::SymbolRefAttr procRef;
    if (parser.parseAttribute(procRef, "funcname", result.attributes))
      return mlir::failure();
    bool hasTuple = false;
    mlir::OpAsmParser::OperandType tupleRef;
    if (!parser.parseOptionalComma()) {
      if (parser.parseOperand(tupleRef))
        return mlir::failure();
      hasTuple = true;
    }
    mlir::FunctionType type;
    if (parser.parseColon() ||
        parser.parseLParen() ||
        parser.parseType(type))
      return mlir::failure();
    result.addAttribute("functype", mlir::TypeAttr::get(type));
    if (hasTuple) {
      mlir::Type tupleType;
      if (parser.parseComma() ||
          parser.parseType(tupleType) ||
          parser.resolveOperand(tupleRef, tupleType, result.operands))
        return mlir::failure();
    }
    mlir::Type boxType;
    if (parser.parseRParen() ||
        parser.parseArrow() ||
        parser.parseType(boxType) ||
        parser.addTypesToList(boxType, result.types))
      return mlir::failure();
    return mlir::success();
  }];

  let printer = [{
    p << ' ' << (*this)->getAttr("funcname");
    auto h = host();
    if (h) {
      p << ", ";
      p.printOperand(h);
    }
    p << " : (" << (*this)->getAttr("functype");
    if (h)
      p << ", " << h.getType();
    p << ") -> " << getType();
  }];

  let verifier = [{
    // host bindings (optional) must be a reference to a tuple
    if (auto h = host()) {
      if (auto r = h.getType().dyn_cast<ReferenceType>()) {
        if (!r.getEleTy().dyn_cast<mlir::TupleType>())
          return mlir::failure();
      } else {
        return mlir::failure();
      }
    }
    return mlir::success();
  }];
}

def fir_UnboxOp : fir_SimpleOp<"unbox", [NoSideEffect]> {
  let summary = "unbox the boxed value into a tuple value";

  let description = [{
    Unbox a boxed value into a result of multiple values from the box's
    component data.  The values are, minimally, a reference to the data of the
    entity, the byte-size of one element, the rank, the type descriptor, a set
    of flags (packed in an integer, and an array of dimension information (of
    size rank).

    ```mlir
      %40   = ... : !fir.box<!fir.type<T>>
      %41:6 = fir.unbox %40 : (!fir.box<!fir.type<T>>) -> (!fir.ref<!fir.type<T>>, i32, i32, !fir.tdesc<!fir.type<T>>, i32, !fir.array<? x index>)
    ```
  }];

  let arguments = (ins fir_BoxType:$box);

  let results = (outs
    fir_ReferenceType,  // pointer to data
    AnyIntegerLike,     // size of a data element
    AnyIntegerLike,     // rank of data
    fir_TypeDescType,   // abstract type descriptor
    AnyIntegerLike,     // attribute flags (bitfields)
    fir_SequenceType    // dimension information (if any)
  );
}

def fir_UnboxCharOp : fir_SimpleOp<"unboxchar", [NoSideEffect]> {
  let summary = "unbox a boxchar value into a pair value";

  let description = [{
    Unboxes a value of `boxchar` type into a pair consisting of a memory
    reference to the CHARACTER data and the LEN type parameter.

    ```mlir
      %45   = ... : !fir.boxchar<1>
      %46:2 = fir.unboxchar %45 : (!fir.boxchar<1>) -> (!fir.ref<!fir.character<1>>, i32)
    ```
  }];

  let arguments = (ins fir_BoxCharType:$boxchar);

  let results = (outs fir_ReferenceType, AnyIntegerLike);
}

def fir_UnboxProcOp : fir_SimpleOp<"unboxproc", [NoSideEffect]> {
  let summary = "unbox a boxproc value into a pair value";

  let description = [{
    Unboxes a value of `boxproc` type into a pair consisting of a procedure
    pointer and a pointer to a host context.

    ```mlir
      %47   = ... : !fir.boxproc<() -> i32>
      %48:2 = fir.unboxproc %47 : (!fir.ref<() -> i32>, !fir.ref<tuple<f32, i32>>)
    ```
  }];

  let verifier = [{
    if (auto eleTy = fir::dyn_cast_ptrEleTy(refTuple().getType()))
      if (eleTy.isa<mlir::TupleType>())
        return mlir::success();
    return emitOpError("second output argument has bad type");
  }];

  let arguments = (ins fir_BoxProcType:$boxproc);

  let results = (outs FunctionType, fir_ReferenceType:$refTuple);
}

def fir_BoxAddrOp : fir_SimpleOneResultOp<"box_addr", [NoSideEffect]> {
  let summary = "return a memory reference to the boxed value";

  let description = [{
    This operator is overloaded to work with values of type `box`,
    `boxchar`, and `boxproc`.  The result for each of these
    cases, respectively, is the address of the data, the address of the
    `CHARACTER` data, and the address of the procedure.

    ```mlir
      %51 = fir.box_addr %box : (!fir.box<f64>) -> !fir.ref<f64>
      %52 = fir.box_addr %boxchar : (!fir.boxchar<1>) -> !fir.ref<!fir.char<1>>
      %53 = fir.box_addr %boxproc : (!fir.boxproc<!P>) -> !fir.ref<!P>
    ```
  }];

  let arguments = (ins fir_BoxType:$val);

  let results = (outs AnyReferenceLike);

  let hasFolder = 1;
}

def fir_BoxCharLenOp : fir_SimpleOp<"boxchar_len", [NoSideEffect]> {
  let summary = "return the LEN type parameter from a boxchar value";

  let description = [{
    Extracts the LEN type parameter from a `boxchar` value.

    ```mlir
      %45 = ... : !boxchar<1>  // CHARACTER(20)
      %59 = fir.boxchar_len %45 : (!fir.boxchar<1>) -> i64  // len=20
    ```
  }];

  let arguments = (ins fir_BoxCharType:$val);

  let results = (outs AnyIntegerLike);

  let hasFolder = 1;
}

def fir_BoxDimsOp : fir_Op<"box_dims", [NoSideEffect]> {
  let summary = "return the dynamic dimension information for the boxed value";

  let description = [{
    Returns the triple of lower bound, extent, and stride for `dim` dimension
    of `val`, which must have a `box` type.  The dimensions are enumerated from
    left to right from 0 to rank-1. This operation has undefined behavior if
    `dim` is out of bounds.

    ```mlir
      %c1   = constant 0 : i32
      %52:3 = fir.box_dims %40, %c1 : (!fir.box<!fir.array<*:f64>>, i32) -> (index, index, index)
    ```

    The above is a request to return the left most row (at index 0) triple from
    the box. The triple will be the lower bound, extent, and byte-stride, which
    are the values encoded in a standard descriptor.
  }];

  let arguments = (ins fir_BoxType:$val, AnyIntegerLike:$dim);

  let results = (outs Index, Index, Index);

  let assemblyFormat = [{
    $val `,` $dim attr-dict `:` functional-type(operands, results)
  }];

  let extraClassDeclaration = [{
    mlir::Type getTupleType();
  }];
}

def fir_BoxEleSizeOp : fir_SimpleOneResultOp<"box_elesize", [NoSideEffect]> {
  let summary = "return the size of an element of the boxed value";

  let description = [{
    Returns the size of an element in an entity of `box` type.  This size may
    not be known until runtime.

    ```mlir
      %53 = fir.box_elesize %40 : (!fir.box<f32>, i32) -> i32  // size=4
      %54 = fir.box_elesize %40 : (!fir.box<!fir.array<*:f32>>, i32) -> i32
    ```

    In the above example, `%53` may box an array of REAL values while `%54`
    must box an array of REAL values (with dynamic rank and extent).
  }];

  let arguments = (ins fir_BoxType:$val);

  let results = (outs AnyIntegerLike);
}

def fir_BoxIsAllocOp : fir_SimpleOp<"box_isalloc", [NoSideEffect]> {
  let summary = "is the boxed value an ALLOCATABLE?";

  let description = [{
    Determine if the boxed value was from an ALLOCATABLE entity. This will
    return true if the originating box value was from a `fir.embox` op
    with a mem-ref value that had the type !fir.heap<T>.

    ```mlir
      %r = ... : !fir.heap<i64>
      %b = fir.embox %r : (!fir.heap<i64>) -> !fir.box<i64>
      %a = fir.box_isalloc %b : (!fir.box<i64>) -> i1  // true
    ```

    The canonical descriptor implementation will carry a flag to record if the
    variable is an `ALLOCATABLE`.
  }];

  let arguments = (ins fir_BoxType:$val);

  let results = (outs BoolLike);
}

def fir_BoxIsArrayOp : fir_SimpleOp<"box_isarray", [NoSideEffect]> {
  let summary = "is the boxed value an array?";

  let description = [{
    Determine if the boxed value has a positive (> 0) rank. This will return
    true if the originating box value was from a fir.embox with a memory
    reference value that had the type !fir.array<T> and/or a shape argument.

    ```mlir
      %r = ... : !fir.ref<i64>
      %c_100 = constant 100 : index
      %d = fir.shape %c_100 : (index) -> !fir.shape<1>
      %b = fir.embox %r(%d) : (!fir.ref<i64>, !fir.shape<1>) -> !fir.box<i64>
      %a = fir.box_isarray %b : (!fir.box<i64>) -> i1  // true
    ```
  }];

  let arguments = (ins fir_BoxType:$val);

  let results = (outs BoolLike);
}

def fir_BoxIsPtrOp : fir_SimpleOp<"box_isptr", [NoSideEffect]> {
  let summary = "is the boxed value a POINTER?";

  let description = [{
    Determine if the boxed value was from a POINTER entity.

    ```mlir
      %p = ... : !fir.ptr<i64>
      %b = fir.embox %p : (!fir.ptr<i64>) -> !fir.box<i64>
      %a = fir.box_isptr %b : (!fir.box<i64>) -> i1  // true
    ```
  }];

  let arguments = (ins fir_BoxType:$val);

  let results = (outs BoolLike);
}

def fir_BoxProcHostOp : fir_SimpleOp<"boxproc_host", [NoSideEffect]> {
  let summary = "returns the host instance pointer (or null)";

  let description = [{
    Extract the host context pointer from a boxproc value.

    ```mlir
      %8 = ... : !fir.boxproc<(!fir.ref<!fir.type<T>>) -> i32>
      %9 = fir.boxproc_host %8 : (!fir.boxproc<(!fir.ref<!fir.type<T>>) -> i32>) -> !fir.ref<tuple<i32, i32>>
    ```

    In the example, the reference to the closure over the host procedure's
    variables is returned. This allows an internal procedure to access the
    host's variables. It is up to lowering to determine the contract between
    the host and the internal procedure.
  }];

  let arguments = (ins fir_BoxProcType:$val);

  let results = (outs fir_ReferenceType);
}

def fir_BoxRankOp : fir_SimpleOneResultOp<"box_rank", [NoSideEffect]> {
  let summary = "return the number of dimensions for the boxed value";

  let description = [{
    Return the rank of a value of `box` type.  If the value is scalar, the
    rank is 0.

    ```mlir
      %57 = fir.box_rank %40 : (!fir.box<!fir.array<*:f64>>) -> i32
      %58 = fir.box_rank %41 : (!fir.box<f64>) -> i32
    ```

    The example `%57` shows how one would determine the rank of an array that
    has deferred rank at runtime. This rank should be at least 1. In %58, the
    descriptor may be either an array or a scalar, so the value is nonnegative.
  }];

  let arguments = (ins fir_BoxType:$val);

  let results = (outs AnyIntegerType);
}

def fir_BoxTypeDescOp : fir_SimpleOneResultOp<"box_tdesc", [NoSideEffect]> {
  let summary = "return the type descriptor for the boxed value";

  let description = [{
    Return the opaque type descriptor of a value of `box` type. A type
    descriptor is an implementation defined value that fully describes a type
    to the Fortran runtime.

    ```mlir
      %7 = fir.box_tdesc %41 : (!fir.box<f64>) -> !fir.tdesc<f64>
    ```
  }];

  let arguments = (ins fir_BoxType:$val);

  let results = (outs fir_TypeDescType);
}

//===----------------------------------------------------------------------===//
// Array value operations
//===----------------------------------------------------------------------===//

// Array value operations are used to capture the semantics of
// Fortran's array expressions in FIR. An abstract array expression is
// evaluated in the following way.
//
//  1. Determination of the iteration space under which the assignment
//     expression is to be evaluated. The iteration space may be implicit
//     (from the shape of the result array) or explicit (defined by the user).
//  2. If there are masking expressions, evaluate (and cache) the
//     masking expression for the iteration space (from 1).
//  3. The rhs of the assignment is evaluated for the iteration space. If
//     masking expressions were present then the rhs is only evaluated where
//     the mask was computed to be true. The entire rhs is completely evaluated
//     before any results are stored to the lhs.
//  4. Each of the result values computed in the previous step are merged back
//     to the lhs array's storage.
//
// The model (in pseudo-code) is thus:
//
//   !- Load the arrays in the expression
//   %10 = array_load A
//   %11 = array_load B
//   !- optional: compute mask values
//   %masks = allocmem array<??xlogical>
//   do_loop_nest %i = ... {
//     %masks[i] = ...
//   }
//   !- Compute every element value "A = B ..."
//   do_loop_nest %i = ... {
//     if (%masks[i]) {
//       array_fetch %11, ...       !- B(...)
//       %20 = ...                  !- element-by-element computation
//       array_update %10, %20, ... !- A(...) = ...
//     }
//   }
//   !- Merge the new and old values into the memory for "A"
//   array_merge_store <updated A> to <A's address>

def fir_ArrayLoadOp : fir_Op<"array_load", [AttrSizedOperandSegments]> {

  let summary = "Load an array as a value.";

  let description = [{
    Load an entire array as a single SSA value.

    ```fortran
      real :: a(o:n,p:m)
      ...
      ... = ... a ...
    ```

    One can use `fir.array_load` to produce an ssa-value that captures an
    immutable value of the entire array `a`, as in the Fortran array expression
    shown above. Subsequent changes to the memory containing the array do not
    alter its composite value. This operation let's one load an array as a
    value while applying a runtime shape, shift, or slice to the memory
    reference, and its semantics guarantee immutability.

    ```mlir
      %s = fir.shape_shift %o, %n, %p, %m : (index, index, index, index) -> !fir.shape<2>
      // load the entire array 'a'
      %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
      // a fir.store here into array %a does not change %v
    ```
  }];

  let arguments = (ins
    Arg<AnyRefOrBox, "", [MemRead]>:$memref,
    Optional<AnyShapeOrShiftType>:$shape,
    Optional<fir_SliceType>:$slice,
    Variadic<AnyIntegerType>:$typeparams
  );

  let results = (outs fir_SequenceType);

  let assemblyFormat = [{
    $memref (`(`$shape^`)`)? (`[`$slice^`]`)? (`typeparams` $typeparams^)?
        attr-dict `:` functional-type(operands, results)
  }];

  let verifier = [{ return ::verify(*this); }];

  let extraClassDeclaration = [{
    std::vector<mlir::Value> getExtents();
  }];
}

def fir_ArrayFetchOp : fir_Op<"array_fetch", [NoSideEffect]> {

  let summary = "Fetch the value of an element of an array value";

  let description = [{
    Fetch the value of an element in an array value.

    ```fortran
      real :: a(n,m)
      ...
      ... a ...
      ... a(r,s+1) ...
    ```

    One can use `fir.array_fetch` to fetch the (implied) value of `a(i,j)` in
    an array expression as shown above. It can also be used to extract the
    element `a(r,s+1)` in the second expression.

    ```mlir
      %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
      // load the entire array 'a'
      %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
      // fetch the value of one of the array value's elements
      %1 = fir.array_fetch %v, %i, %j : (!fir.array<?x?xf32>, index, index) -> f32
    ```

    It is only possible to use `array_fetch` on an `array_load` result value.
  }];

  let arguments = (ins
    fir_SequenceType:$sequence,
    Variadic<AnyCoordinateType>:$indices
  );

  let results = (outs AnyType:$element);

  let assemblyFormat = [{
    $sequence `,` $indices attr-dict `:` functional-type(operands, results)
  }];

  let verifier = [{
    auto arrTy = sequence().getType().cast<fir::SequenceType>();
    if (indices().size() != arrTy.getDimension())
      return emitOpError("number of indices != dimension of array");
    if (element().getType() != arrTy.getEleTy())
      return emitOpError("return type does not match array");
    if (!isa<fir::ArrayLoadOp>(sequence().getDefiningOp()))
      return emitOpError("argument #0 must be result of fir.array_load");
    return mlir::success();
  }];
}

def fir_ArrayUpdateOp : fir_Op<"array_update", [NoSideEffect]> {

  let summary = "Update the value of an element of an array value";

  let description = [{
    Updates the value of an element in an array value. A new array value is
    returned where all element values of the input array are identical except
    for the selected element which is the value passed in the update.

    ```fortran
      real :: a(n,m)
      ...
      a = ...
    ```

    One can use `fir.array_update` to update the (implied) value of `a(i,j)`
    in an array expression as shown above.

    ```mlir
      %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
      // load the entire array 'a'
      %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
      // update the value of one of the array value's elements
      // %r_{ij} = %f  if (i,j) = (%i,%j),   %v_{ij} otherwise
      %r = fir.array_update %v, %f, %i, %j : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
      fir.array_merge_store %v, %r to %a : !fir.ref<!fir.array<?x?xf32>>
    ```

    An array value update behaves as if a mapping function from the indices
    to the new value has been added, replacing the previous mapping. These
    mappings can be added to the ssa-value, but will not be materialized in
    memory until the `fir.array_merge_store` is performed.
  }];

  let arguments = (ins
    fir_SequenceType:$sequence,
    AnyType:$merge,
    Variadic<AnyCoordinateType>:$indices
  );

  let results = (outs fir_SequenceType);

  let assemblyFormat = [{
    $sequence `,` $merge `,` $indices attr-dict `:` functional-type(operands, results)
  }];

  let verifier = [{
    auto arrTy = sequence().getType().cast<fir::SequenceType>();
    if (merge().getType() != arrTy.getEleTy())
      return emitOpError("merged value does not have element type");
    if (indices().size() != arrTy.getDimension())
      return emitOpError("number of indices != dimension of array");
    return mlir::success();
  }];
}

def fir_ArrayMergeStoreOp : fir_Op<"array_merge_store", [
    TypesMatchWith<"type of 'original' matches element type of 'memref'",
                     "memref", "original",
                     "fir::dyn_cast_ptrOrBoxEleTy($_self)">,
    TypesMatchWith<"type of 'sequence' matches element type of 'memref'",
                     "memref", "sequence",
                     "fir::dyn_cast_ptrOrBoxEleTy($_self)">]> {

  let summary = "Store merged array value to memory.";

  let description = [{
    Store a merged array value to memory.

    ```fortran
      real :: a(n,m)
      ...
      a = ...
    ```

    One can use `fir.array_merge_store` to merge/copy the value of `a` in an
    array expression as shown above.

    ```mlir
      %v = fir.array_load %a(%shape) : ...
      %r = fir.array_update %v, %f, %i, %j : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
      fir.array_merge_store %v, %r to %a : !fir.ref<!fir.array<?x?xf32>>
    ```

    This operation merges the original loaded array value, `%v`, with the
    chained updates, `%r`, and stores the result to the array at address, `%a`.
  }];

  let arguments = (ins
    fir_SequenceType:$original,
    fir_SequenceType:$sequence,
    Arg<AnyRefOrBox, "", [MemWrite]>:$memref
  );

  let assemblyFormat = "$original `,` $sequence `to` $memref attr-dict `:` type($memref)";

  let verifier = [{
    if (!isa<ArrayLoadOp>(original().getDefiningOp()))
       return emitOpError("operand #0 must be result of a fir.array_load op");
    return mlir::success();
  }];
}

//===----------------------------------------------------------------------===//
// Record and array type operations
//===----------------------------------------------------------------------===//

def fir_ArrayCoorOp : fir_Op<"array_coor",
    [NoSideEffect, AttrSizedOperandSegments]> {

  let summary = "Find the coordinate of an element of an array";

  let description = [{
    Compute the location of an element in an array when the shape of the
    array is only known at runtime.

    This operation is intended to capture all the runtime values needed to
    compute the address of an array reference in a single high-level op. Given
    the following Fortran input:

    ```fortran
      real :: a(n,m)
      ...
      ... a(i,j) ...
    ```

    One can use `fir.array_coor` to determine the address of `a(i,j)`.

    ```mlir
      %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
      %1 = fir.array_coor %a(%s) %i, %j : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>, index, index) -> !fir.ref<f32>
    ```
  }];

  let arguments = (ins
    AnyRefOrBox:$memref,
    Optional<AnyShapeOrShiftType>:$shape,
    Optional<fir_SliceType>:$slice,
    Variadic<AnyCoordinateType>:$indices,
    Variadic<AnyIntegerType>:$lenParams
  );

  let results = (outs fir_ReferenceType);

  let assemblyFormat = [{
    $memref (`(`$shape^`)`)? (`[`$slice^`]`)? $indices (`typeparams` $lenParams^)? attr-dict `:` functional-type(operands, results)
  }];

  let verifier = [{ return ::verify(*this); }];
}

def fir_CoordinateOp : fir_Op<"coordinate_of", [NoSideEffect]> {

  let summary = "Finds the coordinate (location) of a value in memory";

  let description = [{
    Compute the internal coordinate address starting from a boxed value or
    unboxed memory reference. Returns a memory reference. When computing the
    coordinate of an array element, the rank of the array must be known and
    the number of indexing expressions must equal the rank of the array.

    This operation will apply the access map from a boxed value implicitly.

    Unlike LLVM's GEP instruction, one cannot stride over the outermost
    reference; therefore, the leading 0 index must be omitted.

    ```mlir
      %i = ... : index
      %h = ... : !fir.heap<!fir.array<100 x f32>>
      %p = fir.coordinate_of %h, %i : (!fir.heap<!fir.array<100 x f32>>, index) -> !fir.ref<f32>
    ```

    In the example, `%p` will be a pointer to the `%i`-th f32 value in the
    array `%h`.
  }];

  let arguments = (ins
    AnyRefOrBox:$ref,
    Variadic<AnyCoordinateType>:$coor,
    TypeAttr:$baseType
  );

  let results = (outs fir_ReferenceType);

  let parser =  [{ return parseCoordinateCustom(parser, result); }];
  let printer = [{ ::print(p, *this); }];
  let verifier = [{ return ::verify(*this); }];

  let builders = [
    OpBuilder<(ins "mlir::Type":$resultType,
      "mlir::Value":$ref, "mlir::ValueRange":$coor),
    [{ return build($_builder, $_state, resultType, ref, coor,
           mlir::TypeAttr::get(ref.getType())); }]>,
  ];

  let extraClassDeclaration = [{
    /// Get the type of the base object.
    mlir::Type getBaseType() { return baseType(); }
  }];
}

def fir_ExtractValueOp : fir_OneResultOp<"extract_value", [NoSideEffect]> {
  let summary = "Extract a value from an aggregate SSA-value";

  let description = [{
    Extract a value from an entity with a type composed of tuples, arrays,
    and/or derived types. Returns the value from entity with the type of the
    specified component. Cannot be used on values of `!fir.box` type.
    It can also be used to access complex parts and elements of a character
    string.

    Note that the entity ssa-value must be of compile-time known size in order
    to use this operation.

    ```mlir
      %f = fir.field_index field, !fir.type<X{field:i32}>
      %s = ... : !fir.type<X>
      %v = fir.extract_value %s, %f : (!fir.type<X>, !fir.field) -> i32
    ```
  }];

  let arguments = (ins
    AnyCompositeLike:$adt,
    Variadic<AnyComponentType>:$coor
  );

  let assemblyFormat = [{
    $adt `,` $coor attr-dict `:` functional-type(operands, results)
  }];
}

def fir_FieldIndexOp : fir_OneResultOp<"field_index", [NoSideEffect]> {
  let summary = "create a field index value from a field identifier";

  let description = [{
    Generate a field (offset) value from an identifier.  Field values may be
    lowered into exact offsets when the layout of a Fortran derived type is
    known at compile-time. The type of a field value is `!fir.field` and
    these values can be used with the `fir.coordinate_of`, `fir.extract_value`,
    or `fir.insert_value` instructions to compute (abstract) addresses of
    subobjects.

    ```mlir
      %f = fir.field_index field, !fir.type<X{field:i32}>
    ```
  }];

  let arguments = (ins
    StrAttr:$field_id,
    TypeAttr:$on_type,
    Variadic<AnyIntegerType>:$lenparams
  );

  let parser = [{
    llvm::StringRef fieldName;
    auto &builder = parser.getBuilder();
    mlir::Type recty;
    if (parser.parseOptionalKeyword(&fieldName) ||
        parser.parseComma() ||
        parser.parseType(recty))
      return mlir::failure();
    result.addAttribute(fieldAttrName(), builder.getStringAttr(fieldName));
    if (!recty.dyn_cast<RecordType>())
      return mlir::failure();
    result.addAttribute(typeAttrName(), mlir::TypeAttr::get(recty));
    if (!parser.parseOptionalLParen()) {
      llvm::SmallVector<mlir::OpAsmParser::OperandType, 8> operands;
      llvm::SmallVector<mlir::Type, 8> types;
      auto loc = parser.getNameLoc();
      if (parser.parseOperandList(operands,
                                  mlir::OpAsmParser::Delimiter::None) ||
          parser.parseColonTypeList(types) ||
          parser.parseRParen() ||
          parser.resolveOperands(operands, types, loc, result.operands))
        return mlir::failure();
    }
    mlir::Type fieldType = fir::FieldType::get(builder.getContext());
    if (parser.addTypeToList(fieldType, result.types))
      return mlir::failure();
    return mlir::success();
  }];

  let printer = [{
    p << ' '
      << (*this)->getAttrOfType<mlir::StringAttr>(fieldAttrName()).getValue()
      << ", " << (*this)->getAttr(typeAttrName());
    if (getNumOperands()) {
      p << '(';
      p.printOperands(lenparams());
      auto sep = ") : ";
      for (auto op : lenparams()) {
        p << sep;
        if (op)
          p.printType(op.getType());
        else
          p << "()";
        sep = ", ";
      }
    }
  }];

  let builders = [OpBuilder<(ins "llvm::StringRef":$fieldName,
      "mlir::Type":$recTy, CArg<"mlir::ValueRange","{}">:$operands),
    [{
      $_state.addAttribute(fieldAttrName(),
        $_builder.getStringAttr(fieldName));
      $_state.addAttribute(typeAttrName(), TypeAttr::get(recTy));
      $_state.addOperands(operands);
    }]
  >];

  let extraClassDeclaration = [{
    static constexpr llvm::StringRef fieldAttrName() { return "field_id"; }
    static constexpr llvm::StringRef typeAttrName() { return "on_type"; }
    llvm::StringRef getFieldName() { return field_id(); }
  }];
}

def fir_ShapeOp : fir_Op<"shape", [NoSideEffect]> {

  let summary = "generate an abstract shape vector of type `!fir.shape`";

  let description = [{
    The arguments are an ordered list of integral type values that define the
    runtime extent of each dimension of an array. The shape information is
    given in the same row-to-column order as Fortran. This abstract shape value
    must be applied to a reified object, so all shape information must be
    specified.  The extent must be nonnegative.

    ```mlir
      %d = fir.shape %row_sz, %col_sz : (index, index) -> !fir.shape<2>
    ```
  }];

  let arguments = (ins Variadic<AnyIntegerType>:$extents);

  let results = (outs fir_ShapeType);

  let assemblyFormat = [{
    operands attr-dict `:` functional-type(operands, results)
  }];

  let verifier = [{
    auto size = extents().size();
    auto shapeTy = getType().dyn_cast<fir::ShapeType>();
    assert(shapeTy && "must be a shape type");
    if (shapeTy.getRank() != size)
      return emitOpError("shape type rank mismatch");
    return mlir::success();
  }];

  let extraClassDeclaration = [{
    std::vector<mlir::Value> getExtents() {
      return {extents().begin(), extents().end()};
    }
  }];
}

def fir_ShapeShiftOp : fir_Op<"shape_shift", [NoSideEffect]> {

  let summary = [{
    generate an abstract shape and shift vector of type `!fir.shapeshift`
  }];

  let description = [{
    The arguments are an ordered list of integral type values that is a multiple
    of 2 in length. Each such pair is defined as: the lower bound and the
    extent for that dimension. The shifted shape information is given in the
    same row-to-column order as Fortran. This abstract shifted shape value must
    be applied to a reified object, so all shifted shape information must be
    specified.  The extent must be nonnegative.

    ```mlir
      %d = fir.shape_shift %lo, %extent : (index, index) -> !fir.shapeshift<1>
    ```
  }];

  let arguments = (ins Variadic<AnyIntegerType>:$pairs);

  let results = (outs fir_ShapeShiftType);

  let assemblyFormat = [{
    operands attr-dict `:` functional-type(operands, results)
  }];

  let verifier = [{
    auto size = pairs().size();
    if (size < 2 || size > 16 * 2)
      return emitOpError("incorrect number of args");
    if (size % 2 != 0)
      return emitOpError("requires a multiple of 2 args");
    auto shapeTy = getType().dyn_cast<fir::ShapeShiftType>();
    assert(shapeTy && "must be a shape shift type");
    if (shapeTy.getRank() * 2 != size)
      return emitOpError("shape type rank mismatch");
    return mlir::success();
  }];

  let extraClassDeclaration = [{
    // Logically unzip the origins from the extent values.
    std::vector<mlir::Value> getOrigins() {
      std::vector<mlir::Value> result;
      for (auto i : llvm::enumerate(pairs()))
        if (!(i.index() & 1))
          result.push_back(i.value());
      return result;
    }

    // Logically unzip the extents from the origin values.
    std::vector<mlir::Value> getExtents() {
      std::vector<mlir::Value> result;
      for (auto i : llvm::enumerate(pairs()))
        if (i.index() & 1)
          result.push_back(i.value());
      return result;
    }
  }];
}

def fir_ShiftOp : fir_Op<"shift", [NoSideEffect]> {

  let summary = "generate an abstract shift vector of type `!fir.shift`";

  let description = [{
    The arguments are an ordered list of integral type values that define the
    runtime lower bound of each dimension of an array. The shape information is
    given in the same row-to-column order as Fortran. This abstract shift value
    must be applied to a reified object, so all shift information must be
    specified.

    ```mlir
      %d = fir.shift %row_lb, %col_lb : (index, index) -> !fir.shift<2>
    ```
  }];

  let arguments = (ins Variadic<AnyIntegerType>:$origins);

  let results = (outs fir_ShiftType);

  let assemblyFormat = [{
    operands attr-dict `:` functional-type(operands, results)
  }];

  let verifier = [{
    auto size = origins().size();
    auto shiftTy = getType().dyn_cast<fir::ShiftType>();
    assert(shiftTy && "must be a shift type");
    if (shiftTy.getRank() != size)
      return emitOpError("shift type rank mismatch");
    return mlir::success();
  }];

  let extraClassDeclaration = [{
    std::vector<mlir::Value> getOrigins() {
      return {origins().begin(), origins().end()};
    }
  }];
}

def fir_SliceOp : fir_Op<"slice", [NoSideEffect, AttrSizedOperandSegments]> {

  let summary = "generate an abstract slice vector of type `!fir.slice`";

  let description = [{
    The array slicing arguments are an ordered list of integral type values
    that must be a multiple of 3 in length.  Each such triple is defined as:
    the lower bound, the upper bound, and the stride for that dimension, as in
    Fortran syntax. Both bounds are inclusive. The array slice information is
    given in the same row-to-column order as Fortran. This abstract slice value
    must be applied to a reified object, so all slice information must be
    specified.  The extent must be nonnegative and the stride must not be zero.

    ```mlir
      %d = fir.slice %lo, %hi, %step : (index, index, index) -> !fir.slice<1>
    ```

    To support generalized slicing of Fortran's dynamic derived types, a slice
    op can be given a component path (narrowing from the product type of the
    original array to the specific elemental type of the sliced projection).

    ```mlir
      %fld = fir.field_index component, !fir.type<t{...component:ct...}>
      %d = fir.slice %lo, %hi, %step path %fld : (index, index, index, !fir.field) -> !fir.slice<1>
    ```
  }];

  let arguments = (ins
    Variadic<AnyCoordinateType>:$triples,
    Variadic<AnyComponentType>:$fields
  );

  let results = (outs fir_SliceType);

  let assemblyFormat = [{
    $triples (`path` $fields^)? attr-dict `:` functional-type(operands, results)
  }];

  let verifier = [{
    auto size = triples().size();
    if (size < 3 || size > 16 * 3)
      return emitOpError("incorrect number of args for triple");
    if (size % 3 != 0)
      return emitOpError("requires a multiple of 3 args");
    auto sliceTy = getType().dyn_cast<fir::SliceType>();
    assert(sliceTy && "must be a slice type");
    if (sliceTy.getRank() * 3 != size)
      return emitOpError("slice type rank mismatch");
    return mlir::success();
  }];

  let extraClassDeclaration = [{
    unsigned getOutRank() { return getOutputRank(triples()); }
    static unsigned getOutputRank(mlir::ValueRange triples);
  }];
}

def fir_InsertValueOp : fir_OneResultOp<"insert_value", [NoSideEffect]> {
  let summary = "insert a new sub-value into a copy of an existing aggregate";

  let description = [{
    Insert a value into an entity with a type composed of tuples, arrays,
    and/or derived types. Returns a new ssa value with the same type as the
    original entity. Cannot be used on values of `!fir.box` type.
    It can also be used to set complex parts and elements of a character
    string.

    Note that the entity ssa-value must be of compile-time known size in order
    to use this operation.

    ```mlir
      %a = ... : !fir.array<10xtuple<i32, f32>>
      %f = ... : f32
      %o = ... : i32
      %c = constant 1 : i32
      %b = fir.insert_value %a, %f, %o, %c : (!fir.array<10x20xtuple<i32, f32>>, f32, i32, i32) -> !fir.array<10x20xtuple<i32, f32>>
    ```
  }];

  let arguments = (ins AnyCompositeLike:$adt, AnyType:$val,
                       Variadic<AnyComponentType>:$coor);
  let results = (outs AnyCompositeLike);

  let assemblyFormat = [{
    operands attr-dict `:` functional-type(operands, results)
  }];

  let hasCanonicalizer = 1;
}

def fir_InsertOnRangeOp : fir_OneResultOp<"insert_on_range", [NoSideEffect]> {
  let summary = "insert sub-value into a range on an existing sequence";

  let description = [{
    Insert copies of a value into an entity with an array type.
    Returns a new ssa value with the same type as the original entity.
    The values are inserted at a contiguous range of indices in Fortran
    row-to-column element order as specified by lower and upper bound
    coordinates.

    ```mlir
      %a = fir.undefined !fir.array<10x10xf32>
      %c = constant 3.0 : f32
      %1 = fir.insert_on_range %a, %c, [0 : index, 7 : index, 0 : index, 2 : index] : (!fir.array<10x10xf32>, f32) -> !fir.array<10x10xf32>
    ```

    The first 28 elements of %1, with coordinates from (0,0) to (7,2), have
    the value 3.0.
  }];

  let arguments = (ins fir_SequenceType:$seq, AnyType:$val, ArrayAttr:$coor);
  let results = (outs fir_SequenceType);

  let assemblyFormat = [{
    $seq `,` $val `,` $coor attr-dict `:` functional-type(operands, results)
  }];

  let builders = [
    OpBuilder<(ins "mlir::Type":$rty, "mlir::Value":$adt, "mlir::Value":$val,
      "llvm::ArrayRef<mlir::Value>":$vcoor)>
  ];

  let verifier = [{ return ::verify(*this); }];
}

def fir_LenParamIndexOp : fir_OneResultOp<"len_param_index", [NoSideEffect]> {
  let summary =
    "create a field index value from a LEN type parameter identifier";

  let description = [{
    Generate a LEN parameter (offset) value from an LEN parameter identifier.
    The type of a LEN parameter value is `!fir.len` and these values can be
    used with the `fir.coordinate_of` instructions to compute (abstract)
    addresses of LEN parameters.

    ```mlir
      %e = fir.len_param_index len1, !fir.type<X(len1:i32)>
      %p = ... : !fir.box<!fir.type<X>>
      %q = fir.coordinate_of %p, %e : (!fir.box<!fir.type<X>>, !fir.len) -> !fir.ref<i32>
    ```
  }];

  let arguments = (ins StrAttr:$field_id, TypeAttr:$on_type);

  let parser = [{
    llvm::StringRef fieldName;
    auto &builder = parser.getBuilder();
    mlir::Type recty;
    if (parser.parseOptionalKeyword(&fieldName) ||
        parser.parseComma() ||
        parser.parseType(recty))
      return mlir::failure();
    result.addAttribute(fieldAttrName(), builder.getStringAttr(fieldName));
    if (!recty.dyn_cast<RecordType>())
      return mlir::failure();
    result.addAttribute(typeAttrName(), mlir::TypeAttr::get(recty));
    mlir::Type lenType = fir::LenType::get(builder.getContext());
    if (parser.addTypeToList(lenType, result.types))
      return mlir::failure();
    return mlir::success();
  }];

  let printer = [{
    p << ' '
      << (*this)->getAttrOfType<mlir::StringAttr>(fieldAttrName()).getValue()
      << ", " << (*this)->getAttr(typeAttrName());
  }];

  let builders = [OpBuilder<(ins "llvm::StringRef":$fieldName,
      "mlir::Type":$recTy),
    [{
      $_state.addAttribute(fieldAttrName(), $_builder.getStringAttr(fieldName));
      $_state.addAttribute(typeAttrName(), TypeAttr::get(recTy));
    }]
  >];

  let extraClassDeclaration = [{
    static constexpr llvm::StringRef fieldAttrName() { return "field_id"; }
    static constexpr llvm::StringRef typeAttrName() { return "on_type"; }
    mlir::Type getOnType() {
      return (*this)->getAttrOfType<TypeAttr>(typeAttrName()).getValue();
    }
  }];
}

//===----------------------------------------------------------------------===//
// Fortran loops
//===----------------------------------------------------------------------===//

def fir_ResultOp : fir_Op<"result",
    [NoSideEffect, ReturnLike, Terminator,
     ParentOneOf<["IfOp", "DoLoopOp", "IterWhileOp"]>]> {
  let summary = "special terminator for use in fir region operations";

  let description = [{
    Result takes a list of ssa-values produced in the block and forwards them
    as a result to the operation that owns the region of the block. The
    operation can retain the values or return them to its parent block
    depending upon its semantics.
  }];

  let arguments = (ins Variadic<AnyType>:$results);
  let builders = [OpBuilder<(ins), [{ /* do nothing */ }]>];

  let assemblyFormat = "($results^ `:` type($results))? attr-dict";

  let verifier = [{ return ::verify(*this); }];
}

def FirRegionTerminator : SingleBlockImplicitTerminator<"ResultOp">;

class region_Op<string mnemonic, list<OpTrait> traits = []> :
    fir_Op<mnemonic,
    !listconcat(traits, [FirRegionTerminator, RecursiveSideEffects])> {
  let printer = [{ return ::print(p, *this); }];
  let verifier = [{ return ::verify(*this); }];
  let parser = [{ return ::parse$cppClass(parser, result); }];
}

def fir_DoLoopOp : region_Op<"do_loop",
    [DeclareOpInterfaceMethods<LoopLikeOpInterface>]> {
  let summary = "generalized loop operation";
  let description = [{
    Generalized high-level looping construct. This operation is similar to
    MLIR's `scf.for`.

    ```mlir
      %l = constant 0 : index
      %u = constant 9 : index
      %s = constant 1 : index
      fir.do_loop %i = %l to %u step %s unordered {
        %x = fir.convert %i : (index) -> i32
        %v = fir.call @compute(%x) : (i32) -> f32
        %p = fir.coordinate_of %A, %i : (!fir.ref<!fir.array<?xf32>>, index) -> !fir.ref<f32>
        fir.store %v to %p : !fir.ref<f32>
      }
    ```

    The above example iterates over the interval `[%l, %u]`. The unordered
    keyword indicates that the iterations can be executed in any order.
  }];

  let arguments = (ins
    Index:$lowerBound,
    Index:$upperBound,
    Index:$step,
    Variadic<AnyType>:$initArgs,
    OptionalAttr<UnitAttr>:$unordered,
    OptionalAttr<UnitAttr>:$finalValue
  );
  let results = (outs Variadic<AnyType>:$results);
  let regions = (region SizedRegion<1>:$region);

  let skipDefaultBuilders = 1;
  let builders = [
    OpBuilder<(ins "mlir::Value":$lowerBound, "mlir::Value":$upperBound,
      "mlir::Value":$step, CArg<"bool", "false">:$unordered,
      CArg<"bool", "false">:$finalCountValue,
      CArg<"mlir::ValueRange", "llvm::None">:$iterArgs,
      CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attributes)>
  ];

  let extraClassDeclaration = [{
    mlir::Value getInductionVar() { return getBody()->getArgument(0); }
    mlir::OpBuilder getBodyBuilder() {
      return OpBuilder(getBody(), std::prev(getBody()->end()));
    }
    mlir::Block::BlockArgListType getRegionIterArgs() {
      return getBody()->getArguments().drop_front();
    }
    mlir::Operation::operand_range getIterOperands() {
      return getOperands().drop_front(getNumControlOperands());
    }

    void setLowerBound(Value bound) { (*this)->setOperand(0, bound); }
    void setUpperBound(Value bound) { (*this)->setOperand(1, bound); }
    void setStep(Value step) { (*this)->setOperand(2, step); }

    /// Number of region arguments for loop-carried values
    unsigned getNumRegionIterArgs() {
      return getBody()->getNumArguments() - 1;
    }
    /// Number of operands controlling the loop: lb, ub, step
    unsigned getNumControlOperands() { return 3; }
    /// Does the operation hold operands for loop-carried values
    bool hasIterOperands() {
      return (*this)->getNumOperands() > getNumControlOperands();
    }
    /// Get Number of loop-carried values
    unsigned getNumIterOperands() {
      return (*this)->getNumOperands() - getNumControlOperands();
    }

    /// Get the body of the loop
    mlir::Block *getBody() { return &region().front(); }

    void setUnordered() {
      unorderedAttr(mlir::UnitAttr::get(getContext()));
    }

    mlir::BlockArgument iterArgToBlockArg(mlir::Value iterArg);
    void resultToSourceOps(llvm::SmallVectorImpl<mlir::Value> &results,
                           unsigned resultNum);
    mlir::Value blockArgToSourceOp(unsigned blockArgNum);
  }];
}

def fir_IfOp : region_Op<"if", [NoRegionArguments]> {
  let summary = "if-then-else conditional operation";
  let description = [{
    Used to conditionally execute operations. This operation is the FIR
    dialect's version of `loop.if`.

    ```mlir
      %56 = ... : i1
      %78 = ... : !fir.ref<!T>
      fir.if %56 {
        fir.store %76 to %78 : !fir.ref<!T>
      } else {
        fir.store %77 to %78 : !fir.ref<!T>
      }
    ```
  }];

  let arguments = (ins I1:$condition);
  let results = (outs Variadic<AnyType>:$results);

  let regions = (region
    SizedRegion<1>:$thenRegion,
    AnyRegion:$elseRegion
  );

  let skipDefaultBuilders = 1;
  let builders = [
    OpBuilder<(ins "mlir::Value":$cond, "bool":$withElseRegion)>,
    OpBuilder<(ins "mlir::TypeRange":$resultTypes, "mlir::Value":$cond,
        "bool":$withElseRegion)>
  ];

  let extraClassDeclaration = [{
    mlir::OpBuilder getThenBodyBuilder() {
      assert(!thenRegion().empty() && "Unexpected empty 'where' region.");
      mlir::Block &body = thenRegion().front();
      return mlir::OpBuilder(&body, std::prev(body.end()));
    }
    mlir::OpBuilder getElseBodyBuilder() {
      assert(!elseRegion().empty() && "Unexpected empty 'other' region.");
      mlir::Block &body = elseRegion().front();
      return mlir::OpBuilder(&body, std::prev(body.end()));
    }

    void resultToSourceOps(llvm::SmallVectorImpl<mlir::Value> &results,
                           unsigned resultNum);
  }];
}

def fir_IterWhileOp : region_Op<"iterate_while",
    [DeclareOpInterfaceMethods<LoopLikeOpInterface>]> {
  let summary = "DO loop with early exit condition";
  let description = [{
    This single-entry, single-exit looping construct is useful for lowering
    counted loops that can exit early such as, for instance, implied-DO loops.
    It is very similar to `fir::DoLoopOp` with the addition that it requires
    a single loop-carried bool value that signals an early exit condition to
    the operation. A `true` disposition means the next loop iteration should
    proceed. A `false` indicates that the `fir.iterate_while` operation should
    terminate and return its iteration arguments. This is a degenerate counted
    loop in that the loop is not guaranteed to execute all iterations.

    An example iterate_while that returns the counter value, the early
    termination condition, and an extra loop-carried value is shown here. This
    loop counts from %lo to %up (inclusive), stepping by %c1, so long as the
    early exit (%ok) is true. The iter_args %sh value is also carried by the
    loop. The result triple is the values of %i=phi(%lo,%i+%c1),
    %ok=phi(%okIn,%okNew), and %sh=phi(%shIn,%shNew) from the last executed
    iteration.

    ```mlir
      %v:3 = fir.iterate_while (%i = %lo to %up step %c1) and (%ok = %okIn) iter_args(%sh = %shIn) -> (index, i1, i16) {
        %shNew = fir.call @bar(%sh) : (i16) -> i16
        %okNew = fir.call @foo(%sh) : (i16) -> i1
        fir.result %i, %okNew, %shNew : index, i1, i16
      }
    ```
  }];

  let arguments = (ins
    Index:$lowerBound,
    Index:$upperBound,
    Index:$step,
    I1:$iterateIn,
    Variadic<AnyType>:$initArgs,
    OptionalAttr<UnitAttr>:$finalValue
  );
  let results = (outs Variadic<AnyType>:$results);
  let regions = (region SizedRegion<1>:$region);

  let skipDefaultBuilders = 1;
  let builders = [
    OpBuilder<(ins "mlir::Value":$lowerBound, "mlir::Value":$upperBound,
      "mlir::Value":$step, "mlir::Value":$iterate,
      CArg<"bool", "false">:$finalCountValue,
      CArg<"mlir::ValueRange", "llvm::None">:$iterArgs,
      CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attributes)>
  ];

  let extraClassDeclaration = [{
    mlir::Block *getBody() { return &region().front(); }
    mlir::Value getIterateVar() { return getBody()->getArgument(1); }
    mlir::Value getInductionVar() { return getBody()->getArgument(0); }
    mlir::OpBuilder getBodyBuilder() {
      return mlir::OpBuilder(getBody(), std::prev(getBody()->end()));
    }
    mlir::Block::BlockArgListType getRegionIterArgs() {
      return getBody()->getArguments().drop_front();
    }
    mlir::Operation::operand_range getIterOperands() {
      return getOperands().drop_front(getNumControlOperands());
    }

    void setLowerBound(Value bound) { (*this)->setOperand(0, bound); }
    void setUpperBound(Value bound) { (*this)->setOperand(1, bound); }
    void setStep(mlir::Value step) { (*this)->setOperand(2, step); }

    /// Number of region arguments for loop-carried values
    unsigned getNumRegionIterArgs() {
      return getBody()->getNumArguments() - 1;
    }
    /// Number of operands controlling the loop
    unsigned getNumControlOperands() { return 3; }
    /// Does the operation hold operands for loop-carried values
    bool hasIterOperands() {
      return (*this)->getNumOperands() > getNumControlOperands();
    }
    /// Get Number of loop-carried values
    unsigned getNumIterOperands() {
      return (*this)->getNumOperands() - getNumControlOperands();
    }

    mlir::BlockArgument iterArgToBlockArg(mlir::Value iterArg);
    void resultToSourceOps(llvm::SmallVectorImpl<mlir::Value> &results,
                           unsigned resultNum);
    mlir::Value blockArgToSourceOp(unsigned blockArgNum);
  }];
}

//===----------------------------------------------------------------------===//
// Procedure call operations
//===----------------------------------------------------------------------===//

def fir_CallOp : fir_Op<"call", [CallOpInterface]> {
  let summary = "call a procedure";

  let description = [{
    Call the specified function or function reference.

    Provides a custom parser and pretty printer to allow a more readable syntax
    in the FIR dialect, e.g. `fir.call @sub(%12)` or `fir.call %20(%22,%23)`.

    ```mlir
      %a = fir.call %funcref(%arg0) : (!fir.ref<f32>) -> f32
      %b = fir.call @function(%arg1, %arg2) : (!fir.ref<f32>, !fir.ref<f32>) -> f32
    ```
  }];

  let arguments = (ins
    OptionalAttr<SymbolRefAttr>:$callee,
    Variadic<AnyType>:$args
  );
  let results = (outs Variadic<AnyType>);

  let parser = "return parseCallOp(parser, result);";
  let printer = "printCallOp(p, *this);";

  let builders = [
    OpBuilder<(ins "mlir::FuncOp":$callee,
        CArg<"mlir::ValueRange", "{}">:$operands),
    [{
      $_state.addOperands(operands);
      $_state.addAttribute(calleeAttrName($_state.name),
                           SymbolRefAttr::get(callee));
      $_state.addTypes(callee.getType().getResults());
    }]>,
    OpBuilder<(ins "mlir::SymbolRefAttr":$callee,
        "llvm::ArrayRef<mlir::Type>":$results,
        CArg<"mlir::ValueRange", "{}">:$operands),
    [{
      $_state.addOperands(operands);
      $_state.addAttribute(calleeAttrName($_state.name), callee);
      $_state.addTypes(results);
    }]>,
    OpBuilder<(ins "llvm::StringRef":$callee,
        "llvm::ArrayRef<mlir::Type>":$results,
        CArg<"mlir::ValueRange", "{}">:$operands),
    [{
      build($_builder, $_state,
            SymbolRefAttr::get($_builder.getContext(), callee), results,
            operands);
    }]>];

  let extraClassDeclaration = [{
    mlir::FunctionType getFunctionType();

    /// Get the argument operands to the called function.
    operand_range getArgOperands() {
      if (calleeAttr())
        return {arg_operand_begin(), arg_operand_end()};
      return {arg_operand_begin() + 1, arg_operand_end()};
    }

    operand_iterator arg_operand_begin() { return operand_begin(); }
    operand_iterator arg_operand_end() { return operand_end(); }

    /// Return the callee of this operation.
    CallInterfaceCallable getCallableForCallee() {
      if (auto calling = calleeAttr())
        return calling;
      return getOperand(0);
    }
  }];
}

def fir_DispatchOp : fir_Op<"dispatch", []> {
  let summary = "call a type-bound procedure";

  let description = [{
    Perform a dynamic dispatch on the method name via the dispatch table
    associated with the first argument.  The attribute 'pass_arg_pos' can be
    used to select a dispatch argument other than the first one.

    ```mlir
      %r = fir.dispatch methodA(%o) : (!fir.box<none>) -> i32
    ```
  }];

  let arguments = (ins
    StrAttr:$method,
    fir_BoxType:$object,
    Variadic<AnyType>:$args
  );

  let results = (outs Variadic<AnyType>);

  let parser = [{
    mlir::FunctionType calleeType;
    llvm::SmallVector<mlir::OpAsmParser::OperandType, 4> operands;
    auto calleeLoc = parser.getNameLoc();
    llvm::StringRef calleeName;
    if (failed(parser.parseOptionalKeyword(&calleeName))) {
      mlir::StringAttr calleeAttr;
      if (parser.parseAttribute(calleeAttr, "method", result.attributes))
        return mlir::failure();
    } else {
      result.addAttribute(methodAttrName(result.name),
          parser.getBuilder().getStringAttr(calleeName));
    }
    if (parser.parseOperandList(operands,
                                mlir::OpAsmParser::Delimiter::Paren) ||
        parser.parseOptionalAttrDict(result.attributes) ||
        parser.parseColonType(calleeType) ||
        parser.addTypesToList(calleeType.getResults(), result.types) ||
        parser.resolveOperands(
            operands, calleeType.getInputs(), calleeLoc, result.operands))
      return mlir::failure();
    return mlir::success();
  }];

  let printer = [{
    p << ' ' << methodAttr() << '(';
    p.printOperand(object());
    if (!args().empty()) {
      p << ", ";
      p.printOperands(args());
    }
    p << ") : ";
    p.printFunctionalType((*this)->getOperandTypes(),
        (*this)->getResultTypes());
  }];

  let extraClassDeclaration = [{
    mlir::FunctionType getFunctionType();
    operand_range getArgOperands() {
      return {arg_operand_begin(), arg_operand_end()};
    }
    // operand[0] is the object (of box type)
    operand_iterator arg_operand_begin() { return operand_begin() + 1; }
    operand_iterator arg_operand_end() { return operand_end(); }
    static constexpr llvm::StringRef passArgAttrName() {
      return "pass_arg_pos";
    }
    unsigned passArgPos();
  }];
}

// Constant operations that support Fortran

def fir_StringLitOp : fir_Op<"string_lit", [NoSideEffect]> {
  let summary = "create a string literal constant";

  let description = [{
    An FIR constant that represents a sequence of characters that correspond
    to Fortran's CHARACTER type, including a LEN.  We support CHARACTER values
    of different KINDs (different constant sizes).

    ```mlir
      %1 = fir.string_lit "Hello, World!"(13) : !fir.char<1> // ASCII
      %2 = fir.string_lit [158, 2345](2) : !fir.char<2>      // Wide chars
    ```
  }];

  let results = (outs fir_CharacterType);

  let parser = [{
    auto &builder = parser.getBuilder();
    mlir::Attribute val;
    mlir::NamedAttrList attrs;
    llvm::SMLoc trailingTypeLoc;
    if (parser.parseAttribute(val, "fake", attrs))
      return mlir::failure();
    if (auto v = val.dyn_cast<mlir::StringAttr>())
      result.attributes.push_back(builder.getNamedAttr(value(), v));
    else if (auto v = val.dyn_cast<mlir::ArrayAttr>())
      result.attributes.push_back(builder.getNamedAttr(xlist(), v));
    else
      return parser.emitError(parser.getCurrentLocation(),
                              "found an invalid constant");
    mlir::IntegerAttr sz;
    mlir::Type type;
    if (parser.parseLParen() ||
        parser.parseAttribute(sz, size(), result.attributes) ||
        parser.parseRParen() ||
        parser.getCurrentLocation(&trailingTypeLoc) ||
        parser.parseColonType(type))
      return mlir::failure();
    auto charTy = type.dyn_cast<fir::CharacterType>();
    if (!charTy)
      return parser.emitError(trailingTypeLoc,
                              "must have character type");
    type = fir::CharacterType::get(builder.getContext(), charTy.getFKind(),
                                   sz.getInt());
    if (!type || parser.addTypesToList(type, result.types))
      return mlir::failure();
    return mlir::success();
  }];

  let printer = [{
    p << ' ' << getValue() << '(';
    p << getSize().cast<mlir::IntegerAttr>().getValue() << ") : ";
    p.printType(getType());
  }];

  let verifier = [{
    if (getSize().cast<mlir::IntegerAttr>().getValue().isNegative())
      return emitOpError("size must be non-negative");
    if (auto xl = (*this)->getAttr(xlist())) {
      auto xList = xl.cast<mlir::ArrayAttr>();
      for (auto a : xList)
        if (!a.isa<mlir::IntegerAttr>())
	    return emitOpError("values in list must be integers");
    }
    return mlir::success();
  }];

  let extraClassDeclaration = [{
    static constexpr const char *size() { return "size"; }
    static constexpr const char *value() { return "value"; }
    static constexpr const char *xlist() { return "xlist"; }

    // Get the LEN attribute of this character constant
    mlir::Attribute getSize() { return (*this)->getAttr(size()); }
    // Get the string value of this character constant
    mlir::Attribute getValue() {
      if (auto attr = (*this)->getAttr(value()))
        return attr;
      return (*this)->getAttr(xlist());
    }

    /// Is this a wide character literal (1 character > 8 bits)
    bool isWideValue();
  }];
}

// Complex operations

class fir_ArithmeticOp<string mnemonic, list<OpTrait> traits = []> :
    fir_Op<mnemonic,
           !listconcat(traits, [NoSideEffect, SameOperandsAndResultType])>,
    Results<(outs AnyType)> {
  let parser = [{
    return impl::parseOneResultSameOperandTypeOp(parser, result);
  }];

  let printer = [{ return printBinaryOp(this->getOperation(), p); }];
}

class fir_UnaryArithmeticOp<string mnemonic, list<OpTrait> traits = []> :
      fir_Op<mnemonic,
             !listconcat(traits, [NoSideEffect, SameOperandsAndResultType])>,
      Results<(outs AnyType)> {
  let parser = [{
    return impl::parseOneResultSameOperandTypeOp(parser, result);
  }];

  let printer = [{ return printUnaryOp(this->getOperation(), p); }];
}

class RealUnaryArithmeticOp<string mnemonic, list<OpTrait> traits = []> :
      fir_UnaryArithmeticOp<mnemonic, traits>,
      Arguments<(ins AnyRealLike:$operand)>;

def fir_NegfOp : RealUnaryArithmeticOp<"negf">;

class RealArithmeticOp<string mnemonic, list<OpTrait> traits = []> :
      fir_ArithmeticOp<mnemonic, traits>,
      Arguments<(ins AnyRealLike:$lhs, AnyRealLike:$rhs)>;

def fir_ModfOp : RealArithmeticOp<"modf">;

def fir_ConstcOp : fir_Op<"constc", [NoSideEffect]> {
  let summary = "create a complex constant";

  let description = [{
    A complex constant. Similar to the standard dialect complex type, but this
    extension allows constants with APFloat values that are not supported in
    the standard dialect.
  }];

  let results = (outs fir_ComplexType);

  let parser = [{
    fir::RealAttr realp;
    fir::RealAttr imagp;
    mlir::Type type;
    if (parser.parseLParen() ||
        parser.parseAttribute(realp, realAttrName(), result.attributes) ||
        parser.parseComma() ||
        parser.parseAttribute(imagp, imagAttrName(), result.attributes) ||
        parser.parseRParen() ||
        parser.parseColonType(type) ||
        parser.addTypesToList(type, result.types))
      return mlir::failure();
    return mlir::success();
  }];

  let printer = [{
    p << " (0x";
    auto f1 = (*this)->getAttr(realAttrName()).cast<mlir::FloatAttr>();
    auto i1 = f1.getValue().bitcastToAPInt();
    p.getStream().write_hex(i1.getZExtValue());
    p << ", 0x";
    auto f2 = (*this)->getAttr(imagAttrName()).cast<mlir::FloatAttr>();
    auto i2 = f2.getValue().bitcastToAPInt();
    p.getStream().write_hex(i2.getZExtValue());
    p << ") : ";
    p.printType(getType());
  }];

  let verifier = [{
    if (!getType().isa<fir::ComplexType>())
      return emitOpError("must be a !fir.complex type");
    return mlir::success();
  }];

  let extraClassDeclaration = [{
    static constexpr llvm::StringRef realAttrName() { return "real"; }
    static constexpr llvm::StringRef imagAttrName() { return "imaginary"; }

    mlir::Attribute getReal() { return (*this)->getAttr(realAttrName()); }
    mlir::Attribute getImaginary() { return (*this)->getAttr(imagAttrName()); }
  }];
}

class ComplexUnaryArithmeticOp<string mnemonic, list<OpTrait> traits = []> :
      fir_UnaryArithmeticOp<mnemonic, traits>,
      Arguments<(ins fir_ComplexType:$operand)>;

def fir_NegcOp : ComplexUnaryArithmeticOp<"negc">;

class ComplexArithmeticOp<string mnemonic, list<OpTrait> traits = []> :
      fir_ArithmeticOp<mnemonic, traits>,
      Arguments<(ins fir_ComplexType:$lhs, fir_ComplexType:$rhs)>;

def fir_AddcOp : ComplexArithmeticOp<"addc", [Commutative]>;
def fir_SubcOp : ComplexArithmeticOp<"subc">;
def fir_MulcOp : ComplexArithmeticOp<"mulc", [Commutative]>;
def fir_DivcOp : ComplexArithmeticOp<"divc">;
// Pow is a builtin call and not a primitive

def fir_CmpcOp : fir_Op<"cmpc",
    [NoSideEffect, SameTypeOperands, SameOperandsAndResultShape]> {
  let summary = "complex floating-point comparison operator";

  let description = [{
    A complex comparison to handle complex types found in FIR.
  }];

  let arguments = (ins fir_ComplexType:$lhs, fir_ComplexType:$rhs);

  let results = (outs AnyLogicalLike);

  let parser = "return parseCmpcOp(parser, result);";

  let printer = "printCmpcOp(p, *this);";

  let builders = [OpBuilder<(ins "mlir::CmpFPredicate":$predicate,
    "mlir::Value":$lhs, "mlir::Value":$rhs), [{
      buildCmpCOp($_builder, $_state, predicate, lhs, rhs);
  }]>];

  let extraClassDeclaration = [{
    static constexpr llvm::StringRef getPredicateAttrName() {
      return "predicate";
    }

    CmpFPredicate getPredicate() {
      return (CmpFPredicate)(*this)->getAttrOfType<mlir::IntegerAttr>(
          getPredicateAttrName()).getInt();
    }

    static CmpFPredicate getPredicateByName(llvm::StringRef name);
  }];
}

// Other misc. operations

def fir_AddrOfOp : fir_OneResultOp<"address_of", [NoSideEffect]> {
  let summary = "convert a symbol to an SSA value";

  let description = [{
    Convert a symbol (a function or global reference) to an SSA-value to be
    used in other Operations. References to Fortran symbols are distinguished
    via this operation from other arbitrary constant values.

    ```mlir
      %p = fir.address_of(@symbol) : !fir.ref<f64>
    ```
  }];

  let arguments = (ins SymbolRefAttr:$symbol);

  let results = (outs AnyAddressableLike:$resTy);

  let assemblyFormat = "`(` $symbol `)` attr-dict `:` type($resTy)";
}

def fir_ConvertOp : fir_OneResultOp<"convert", [NoSideEffect]> {
  let summary = "encapsulates all Fortran scalar type conversions";

  let description = [{
    Generalized type conversion. Convert the ssa value from type T to type U.
    Not all pairs of types have conversions. When types T and U are the same
    type, this instruction is a NOP and may be folded away.

    ```mlir
      %v = ... : i64
      %w = fir.convert %v : (i64) -> i32
    ```

    The example truncates the value `%v` from an i64 to an i32.
  }];

  let arguments = (ins AnyType:$value);

  let assemblyFormat = [{
    $value attr-dict `:` functional-type($value, results)
  }];

  let hasFolder = 1;

  let verifier = [{
    auto inType = value().getType();
    auto outType = getType();
    if (inType == outType)
      return mlir::success();
    if ((isPointerCompatible(inType) && isPointerCompatible(outType)) ||
        (isIntegerCompatible(inType) && isIntegerCompatible(outType)) ||
        (isIntegerCompatible(inType) && isFloatCompatible(outType)) ||
        (isFloatCompatible(inType) && isIntegerCompatible(outType)) ||
        (isFloatCompatible(inType) && isFloatCompatible(outType)) ||
        (isIntegerCompatible(inType) && isPointerCompatible(outType)) ||
        (isPointerCompatible(inType) && isIntegerCompatible(outType)) ||
        (inType.isa<fir::BoxType>() && outType.isa<fir::BoxType>()) ||
        (fir::isa_complex(inType) && fir::isa_complex(outType)))
      return mlir::success();
    return emitOpError("invalid type conversion");
  }];

  let extraClassDeclaration = [{
    static bool isIntegerCompatible(mlir::Type ty);
    static bool isFloatCompatible(mlir::Type ty);
    static bool isPointerCompatible(mlir::Type ty);
  }];
  let hasCanonicalizer = 1;
}

def FortranTypeAttr : Attr<And<[CPred<"$_self.isa<TypeAttr>()">,
    Or<[CPred<"$_self.cast<TypeAttr>().getValue().isa<fir::CharacterType>()">,
        CPred<"$_self.cast<TypeAttr>().getValue().isa<fir::ComplexType>()">,
        CPred<"$_self.cast<TypeAttr>().getValue().isa<fir::IntegerType>()">,
        CPred<"$_self.cast<TypeAttr>().getValue().isa<fir::LogicalType>()">,
        CPred<"$_self.cast<TypeAttr>().getValue().isa<fir::RealType>()">,
        CPred<"$_self.cast<TypeAttr>().getValue().isa<fir::RecordType>()">]>]>,
    "Fortran surface type"> {
  let storageType = [{ TypeAttr }];
  let returnType = "Type";
  let convertFromStorage = "$_self.getValue().cast<Type>()";
}

def fir_GenTypeDescOp : fir_OneResultOp<"gentypedesc", [NoSideEffect]> {
  let summary = "generate a type descriptor for a given type";
  let description = [{
    Generates a constant object that is an abstract type descriptor of the
    specified type.  The meta-type of a type descriptor for the type `T`
    is `!fir.tdesc<T>`.

    ```mlir
      !T = type !fir.type<T{...}>
      %t = fir.gentypedesc !T  // returns value of !fir.tdesc<!T>
    ```
  }];

  let arguments = (ins FortranTypeAttr:$in_type);

  let parser = [{
    mlir::Type intype;
    if (parser.parseType(intype))
      return mlir::failure();
    result.addAttribute("in_type", mlir::TypeAttr::get(intype));
    mlir::Type restype = TypeDescType::get(intype);
    if (parser.addTypeToList(restype, result.types))
      return mlir::failure();
    return mlir::success();
  }];

  let printer = [{
    p << ' ' << (*this)->getAttr("in_type");
    p.printOptionalAttrDict((*this)->getAttrs(), {"in_type"});
  }];

  let builders = [OpBuilder<(ins "mlir::TypeAttr":$inty)>];

  let verifier = [{
    mlir::Type resultTy = getType();
    if (auto tdesc = resultTy.dyn_cast<TypeDescType>()) {
      if (tdesc.getOfTy() != getInType())
        return emitOpError("wrapped type mismatched");
    } else {
      return emitOpError("must be !fir.tdesc type");
    }
    return mlir::success();
  }];

  let extraClassDeclaration = [{
    mlir::Type getInType() {
      // get the type that the type descriptor describes
      return (*this)->getAttrOfType<mlir::TypeAttr>("in_type").getValue();
    }
  }];
}

def fir_NoReassocOp : fir_OneResultOp<"no_reassoc",
    [NoSideEffect, SameOperandsAndResultType]> {
  let summary = "synthetic op to prevent reassociation";
  let description = [{
    Primitive operation meant to intrusively prevent operator reassociation.
    The operation is otherwise a nop and the value returned is the same as the
    argument.

    The presence of this operation prevents any local optimizations. In the
    example below, this would prevent possibly replacing the multiply and add
    operations with a single FMA operation.

    ```mlir
      %98 = mulf %96, %97 : f32
      %99 = fir.no_reassoc %98 : f32
      %a0 = addf %99, %95 : f32
    ```
  }];

  let arguments = (ins AnyType:$val);

  let assemblyFormat = "$val attr-dict `:` type($val)";
}

class AtMostRegion<int numBlocks> : Region<
  CPred<"$_self.getBlocks().size() <= " # numBlocks>,
  "region with " # numBlocks # " blocks">;

def fir_GlobalOp : fir_Op<"global", [IsolatedFromAbove, Symbol]> {
  let summary = "Global data";
  let description = [{
    A global variable or constant with initial values.

    The example creates a global variable (writable) named
    `@_QV_Mquark_Vvarble` with some initial values. The initializer should
    conform to the variable's type.

    ```mlir
      fir.global @_QV_Mquark_Vvarble : tuple<i32, f32> {
        %1 = constant 1 : i32
        %2 = constant 2.0 : f32
        %3 = fir.undefined tuple<i32, f32>
        %z = constant 0 : index
        %o = constant 1 : index
        %4 = fir.insert_value %3, %1, %z : (tuple<i32, f32>, i32, index) -> tuple<i32, f32>
        %5 = fir.insert_value %4, %2, %o : (tuple<i32, f32>, f32, index) -> tuple<i32, f32>
        fir.has_value %5 : tuple<i32, f32>
      }
    ```
  }];

  let arguments = (ins
    StrAttr:$sym_name,
    SymbolRefAttr:$symref,
    TypeAttr:$type,
    OptionalAttr<AnyAttr>:$initVal,
    OptionalAttr<UnitAttr>:$constant,
    OptionalAttr<StrAttr>:$linkName
  );

  let regions = (region AtMostRegion<1>:$region);

  let parser = "return parseGlobalOp(parser, result);";

  let printer = [{
    if (linkName().hasValue())
      p << ' ' << linkName().getValue();
    p << ' ';
    p.printAttributeWithoutType((*this)->getAttr(symbolAttrName()));
    if (auto val = getValueOrNull())
      p << '(' << val << ')';
    if (constantAttr())
      p << " constant";
    p << " : ";
    p.printType(getType());
    if (hasInitializationBody())
      p.printRegion((*this)->getRegion(0), /*printEntryBlockArgs=*/false,
                    /*printBlockTerminators=*/true);
  }];

  let skipDefaultBuilders = 1;
  let builders = [
    OpBuilder<(ins "llvm::StringRef":$name, "mlir::Type":$type,
      CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs)>,
    OpBuilder<(ins "llvm::StringRef":$name, "bool":$isConstant,
      "mlir::Type":$type,
      CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs)>,
    OpBuilder<(ins "llvm::StringRef":$name, "mlir::Type":$type,
      CArg<"mlir::StringAttr", "{}">:$linkage,
      CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs)>,
    OpBuilder<(ins "llvm::StringRef":$name, "bool":$isConstant,
      "mlir::Type":$type, CArg<"mlir::StringAttr", "{}">:$linkage,
      CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs)>,
    OpBuilder<(ins "llvm::StringRef":$name, "mlir::Type":$type,
      "mlir::Attribute":$initVal, CArg<"mlir::StringAttr", "{}">:$linkage,
      CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs)>,
    OpBuilder<(ins "llvm::StringRef":$name, "bool":$isConstant,
      "mlir::Type":$type, "mlir::Attribute":$initVal,
      CArg<"mlir::StringAttr", "{}">:$linkage,
      CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs)>,
  ];

  let extraClassDeclaration = [{
    static constexpr llvm::StringRef symbolAttrName() { return "symref"; }
    static constexpr llvm::StringRef linkageAttrName() { return "linkName"; }

    /// The printable type of the global
    mlir::Type getType() {
      return typeAttr().getValue();
    }

    /// The semantic type of the global
    mlir::Type resultType() {
      return fir::AllocaOp::wrapResultType(getType());
    }

    /// Return the initializer attribute if it exists, or a null attribute.
    Attribute getValueOrNull() { return initVal().getValueOr(Attribute()); }

    /// Append the next initializer value to the `GlobalOp` to construct
    /// the variable's initial value.
    void appendInitialValue(mlir::Operation *op);

    /// A GlobalOp has one region.
    mlir::Region &getRegion() { return (*this)->getRegion(0); }

    /// A GlobalOp has one block.
    mlir::Block &getBlock() { return getRegion().front(); }

    /// Determine if `linkage` is a supported keyword
    static mlir::ParseResult verifyValidLinkage(StringRef linkage);

    bool hasInitializationBody() {
      return ((*this)->getNumRegions() == 1) && !getRegion().empty() &&
        !isa<fir::FirEndOp>(getBlock().front());
    }

    mlir::FlatSymbolRefAttr getSymbol() {
      return mlir::FlatSymbolRefAttr::get(getContext(),
          (*this)->getAttrOfType<mlir::StringAttr>(
              mlir::SymbolTable::getSymbolAttrName()).getValue());
    }
  }];
}

def fir_GlobalLenOp : fir_Op<"global_len", []> {
  let summary = "map a LEN parameter to a global";
  let description = [{
    A global entity (that is not an automatic data object) can have extra LEN
    parameter (compile-time) constants associated with the instance's type.
    These values can be bound to the global instance used `fir.global_len`.

    ```mlir
      global @g : !fir.type<t(len1:i32)> {
        fir.global_len len1, 10 : i32
        %1 = fir.undefined : !fir.type<t(len1:i32)>
        return %1 : !fir.type<t(len1:i32)>
      }
    ```
  }];

  let arguments = (ins StrAttr:$lenparam, APIntAttr:$intval);

  let parser = [{
    llvm::StringRef fieldName;
    if (failed(parser.parseOptionalKeyword(&fieldName))) {
      mlir::StringAttr fieldAttr;
      if (parser.parseAttribute(fieldAttr, lenParamAttrName(),
                                result.attributes))
        return mlir::failure();
    } else {
      result.addAttribute(lenParamAttrName(),
          parser.getBuilder().getStringAttr(fieldName));
    }
    mlir::IntegerAttr constant;
    if (parser.parseComma() ||
        parser.parseAttribute(constant, intAttrName(), result.attributes))
      return mlir::failure();
    return mlir::success();
  }];

  let printer = [{
    p << ' ' << (*this)->getAttr(lenParamAttrName())
      << ", " << (*this)->getAttr(intAttrName());
  }];

  let extraClassDeclaration = [{
    static constexpr llvm::StringRef lenParamAttrName() { return "lenparam"; }
    static constexpr llvm::StringRef intAttrName() { return "intval"; }
  }];
}

def ImplicitFirTerminator : SingleBlockImplicitTerminator<"FirEndOp">;

def fir_DispatchTableOp : fir_Op<"dispatch_table",
    [IsolatedFromAbove, Symbol, ImplicitFirTerminator]> {
  let summary = "Dispatch table definition";

  let description = [{
    Define a dispatch table for a derived type with type-bound procedures.

    A dispatch table is an untyped symbol that contains a list of associations
    between method identifiers and corresponding `FuncOp` symbols.

    The ordering of associations in the map is determined by the front-end.

    ```mlir
      fir.dispatch_table @_QDTMquuzTfoo {
        fir.dt_entry method1, @_QFNMquuzTfooPmethod1AfooR
        fir.dt_entry method2, @_QFNMquuzTfooPmethod2AfooII
      }
    ```
  }];

  let parser = [{
    // Parse the name as a symbol reference attribute.
    SymbolRefAttr nameAttr;
    if (parser.parseAttribute(nameAttr, mlir::SymbolTable::getSymbolAttrName(),
                              result.attributes))
      return failure();

    // Convert the parsed name attr into a string attr.
    result.attributes.set(mlir::SymbolTable::getSymbolAttrName(),
      nameAttr.getRootReference());

    // Parse the optional table body.
    mlir::Region *body = result.addRegion();
    OptionalParseResult parseResult = parser.parseOptionalRegion(*body);
    if (parseResult.hasValue() && failed(*parseResult))
      return mlir::failure();

    ensureTerminator(*body, parser.getBuilder(), result.location);
    return mlir::success();
  }];

  let printer = [{
    auto tableName = (*this)->getAttrOfType<StringAttr>(
      mlir::SymbolTable::getSymbolAttrName()).getValue();
    p << " @" << tableName;

    Region &body = (*this)->getRegion(0);
    if (!body.empty())
      p.printRegion(body, /*printEntryBlockArgs=*/false,
                          /*printBlockTerminators=*/false);
  }];

  let verifier = [{
    for (auto &op : getBlock())
      if (!(isa<fir::DTEntryOp>(op) || isa<fir::FirEndOp>(op)))
        return emitOpError("dispatch table must contain dt_entry");
    return mlir::success();
  }];

  let regions = (region SizedRegion<1>:$region);

  let skipDefaultBuilders = 1;
  let builders = [
    OpBuilder<(ins "llvm::StringRef":$name, "mlir::Type":$type,
      CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs),
    [{
      $_state.addAttribute(mlir::SymbolTable::getSymbolAttrName(),
                           $_builder.getStringAttr(name));
      $_state.addAttributes(attrs);
    }]>
  ];

  let extraClassDeclaration = [{
    /// Append a dispatch table entry to the table.
    void appendTableEntry(mlir::Operation *op);

    mlir::Region &getRegion() {
      return (*this)->getRegion(0);
    }

    mlir::Block &getBlock() {
      return getRegion().front();
    }
  }];
}

def fir_DTEntryOp : fir_Op<"dt_entry", []> {
  let summary = "map entry in a dispatch table";

  let description = [{
    An entry in a dispatch table.  Allows a function symbol to be bound
    to a specifier method identifier.  A dispatch operation uses the dynamic
    type of a distinguished argument to determine an exact dispatch table
    and uses the method identifier to select the type-bound procedure to
    be called.

    ```mlir
      fir.dt_entry method_name, @uniquedProcedure
    ```
  }];

  let arguments = (ins StrAttr:$method, SymbolRefAttr:$proc);

  let parser = [{
    llvm::StringRef methodName;
    // allow `methodName` or `"methodName"`
    if (failed(parser.parseOptionalKeyword(&methodName))) {
      mlir::StringAttr methodAttr;
      if (parser.parseAttribute(methodAttr, "method",
                                result.attributes))
        return mlir::failure();
    } else {
      result.addAttribute(methodAttrName(result.name),
          parser.getBuilder().getStringAttr(methodName));
    }
    mlir::SymbolRefAttr calleeAttr;
    if (parser.parseComma() ||
        parser.parseAttribute(calleeAttr, "proc", result.attributes))
      return mlir::failure();
    return mlir::success();
  }];

  let printer = [{
    p << ' ' << methodAttr() << ", "
      << procAttr();
  }];
}

def fir_AbsentOp : fir_OneResultOp<"absent", [NoSideEffect]> {
  let summary = "create value to be passed for absent optional function argument";
  let description = [{
    Given the type of a function argument, create a value that will signal that
    an optional argument is absent in the call. On the caller side, fir.is_present
    can be used to query if the value of an optional argument was created with
    a fir.absent operation.
    It is undefined to use a value that was created by a fir.absent op in any other
    operation than fir.call and fir.is_present.
    ```mlir
      %1 = fir.absent fir.box<fir.array<?xf32>>
      fir.call @_QPfoo(%1) : (fir.box<fir.array<?xf32>>) -> ()
    ```
  }];

  let results = (outs AnyRefOrBoxLike:$intype);

  let assemblyFormat = "type($intype) attr-dict";
}

def fir_IsPresentOp : fir_SimpleOp<"is_present", [NoSideEffect]> {
  let summary = "is this optional function argument present?";

  let description = [{
    Determine if an optional function argument is PRESENT (i.e. that it was not
    created by a fir.absent op on the caller side).
    ```mlir
      func @_QPfoo(%arg0: !fir.box<!fir.array<?xf32>>) {
        %0 = fir.is_present %arg0 : (!fir.box<!fir.array<?xf32>>) -> i1
        ...
    ```
  }];

  let arguments = (ins AnyRefOrBoxLike:$val);

  let results = (outs BoolLike);
}

#endif
