//===- LLVMDialect.cpp - LLVM IR Ops and Dialect registration -------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file defines the types and operation details for the LLVM IR dialect in
// MLIR, and the LLVM IR dialect.  It also registers the dialect.
//
//===----------------------------------------------------------------------===//

#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/DialectImplementation.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/Matchers.h"
#include "mlir/Interfaces/FunctionImplementation.h"
#include "mlir/Transforms/InliningUtils.h"

#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Support/Error.h"

#include "LLVMDialectBytecode.h"

#include <numeric>
#include <optional>

using namespace mlir;
using namespace mlir::LLVM;
using mlir::LLVM::cconv::getMaxEnumValForCConv;
using mlir::LLVM::linkage::getMaxEnumValForLinkage;
using mlir::LLVM::tailcallkind::getMaxEnumValForTailCallKind;

#include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"

//===----------------------------------------------------------------------===//
// Attribute Helpers
//===----------------------------------------------------------------------===//

static constexpr const char kElemTypeAttrName[] = "elem_type";

static auto processFMFAttr(ArrayRef<NamedAttribute> attrs) {
  SmallVector<NamedAttribute, 8> filteredAttrs(
      llvm::make_filter_range(attrs, [&](NamedAttribute attr) {
        if (attr.getName() == "fastmathFlags") {
          auto defAttr =
              FastmathFlagsAttr::get(attr.getValue().getContext(), {});
          return defAttr != attr.getValue();
        }
        return true;
      }));
  return filteredAttrs;
}

/// Verifies `symbol`'s use in `op` to ensure the symbol is a valid and
/// fully defined llvm.func.
static LogicalResult verifySymbolAttrUse(FlatSymbolRefAttr symbol,
                                         Operation *op,
                                         SymbolTableCollection &symbolTable) {
  StringRef name = symbol.getValue();
  auto func =
      symbolTable.lookupNearestSymbolFrom<LLVMFuncOp>(op, symbol.getAttr());
  if (!func)
    return op->emitOpError("'")
           << name << "' does not reference a valid LLVM function";
  if (func.isExternal())
    return op->emitOpError("'") << name << "' does not have a definition";
  return success();
}

/// Returns a boolean type that has the same shape as `type`. It supports both
/// fixed size vectors as well as scalable vectors.
static Type getI1SameShape(Type type) {
  Type i1Type = IntegerType::get(type.getContext(), 1);
  if (LLVM::isCompatibleVectorType(type))
    return LLVM::getVectorType(i1Type, LLVM::getVectorNumElements(type));
  return i1Type;
}

// Parses one of the keywords provided in the list `keywords` and returns the
// position of the parsed keyword in the list. If none of the keywords from the
// list is parsed, returns -1.
static int parseOptionalKeywordAlternative(OpAsmParser &parser,
                                           ArrayRef<StringRef> keywords) {
  for (const auto &en : llvm::enumerate(keywords)) {
    if (succeeded(parser.parseOptionalKeyword(en.value())))
      return en.index();
  }
  return -1;
}

namespace {
template <typename Ty>
struct EnumTraits {};

#define REGISTER_ENUM_TYPE(Ty)                                                 \
  template <>                                                                  \
  struct EnumTraits<Ty> {                                                      \
    static StringRef stringify(Ty value) { return stringify##Ty(value); }      \
    static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); }         \
  }

REGISTER_ENUM_TYPE(Linkage);
REGISTER_ENUM_TYPE(UnnamedAddr);
REGISTER_ENUM_TYPE(CConv);
REGISTER_ENUM_TYPE(TailCallKind);
REGISTER_ENUM_TYPE(ThreadLocalMode);
REGISTER_ENUM_TYPE(Visibility);
} // namespace

/// Parse an enum from the keyword, or default to the provided default value.
/// The return type is the enum type by default, unless overridden with the
/// second template argument.
template <typename EnumTy, typename RetTy = EnumTy>
static RetTy parseOptionalLLVMKeyword(OpAsmParser &parser,
                                      EnumTy defaultValue) {
  SmallVector<StringRef, 10> names;
  for (unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
    names.push_back(EnumTraits<EnumTy>::stringify(static_cast<EnumTy>(i)));

  int index = parseOptionalKeywordAlternative(parser, names);
  if (index == -1)
    return static_cast<RetTy>(defaultValue);
  return static_cast<RetTy>(index);
}

static void printLLVMLinkage(OpAsmPrinter &p, Operation *, LinkageAttr val) {
  p << stringifyLinkage(val.getLinkage());
}

static ParseResult parseLLVMLinkage(OpAsmParser &p, LinkageAttr &val) {
  val = LinkageAttr::get(
      p.getContext(),
      parseOptionalLLVMKeyword<LLVM::Linkage>(p, LLVM::Linkage::External));
  return success();
}

static ArrayAttr getLLVMAlignParamForCompressExpand(OpBuilder &builder,
                                                    bool isExpandLoad,
                                                    uint64_t alignment = 1) {
  // From
  // https://llvm.org/docs/LangRef.html#llvm-masked-expandload-intrinsics
  // https://llvm.org/docs/LangRef.html#llvm-masked-compressstore-intrinsics
  //
  //   The pointer alignment defaults to 1.
  if (alignment == 1) {
    return nullptr;
  }

  auto emptyDictAttr = builder.getDictionaryAttr({});
  auto alignmentAttr = builder.getI64IntegerAttr(alignment);
  auto namedAttr =
      builder.getNamedAttr(LLVMDialect::getAlignAttrName(), alignmentAttr);
  SmallVector<mlir::NamedAttribute> attrs = {namedAttr};
  auto alignDictAttr = builder.getDictionaryAttr(attrs);
  // From
  // https://llvm.org/docs/LangRef.html#llvm-masked-expandload-intrinsics
  // https://llvm.org/docs/LangRef.html#llvm-masked-compressstore-intrinsics
  //
  //   The align parameter attribute can be provided for [expandload]'s first
  //   argument. The align parameter attribute can be provided for
  //   [compressstore]'s second argument.
  int pos = isExpandLoad ? 0 : 1;
  return pos == 0 ? builder.getArrayAttr(
                        {alignDictAttr, emptyDictAttr, emptyDictAttr})
                  : builder.getArrayAttr(
                        {emptyDictAttr, alignDictAttr, emptyDictAttr});
}

//===----------------------------------------------------------------------===//
// Operand bundle helpers.
//===----------------------------------------------------------------------===//

static void printOneOpBundle(OpAsmPrinter &p, OperandRange operands,
                             TypeRange operandTypes, StringRef tag) {
  p.printString(tag);
  p << "(";

  if (!operands.empty()) {
    p.printOperands(operands);
    p << " : ";
    llvm::interleaveComma(operandTypes, p);
  }

  p << ")";
}

static void printOpBundles(OpAsmPrinter &p, Operation *op,
                           OperandRangeRange opBundleOperands,
                           TypeRangeRange opBundleOperandTypes,
                           std::optional<ArrayAttr> opBundleTags) {
  if (opBundleOperands.empty())
    return;
  assert(opBundleTags && "expect operand bundle tags");

  p << "[";
  llvm::interleaveComma(
      llvm::zip(opBundleOperands, opBundleOperandTypes, *opBundleTags), p,
      [&p](auto bundle) {
        auto bundleTag = cast<StringAttr>(std::get<2>(bundle)).getValue();
        printOneOpBundle(p, std::get<0>(bundle), std::get<1>(bundle),
                         bundleTag);
      });
  p << "]";
}

static ParseResult parseOneOpBundle(
    OpAsmParser &p,
    SmallVector<SmallVector<OpAsmParser::UnresolvedOperand>> &opBundleOperands,
    SmallVector<SmallVector<Type>> &opBundleOperandTypes,
    SmallVector<Attribute> &opBundleTags) {
  SMLoc currentParserLoc = p.getCurrentLocation();
  SmallVector<OpAsmParser::UnresolvedOperand> operands;
  SmallVector<Type> types;
  std::string tag;

  if (p.parseString(&tag))
    return p.emitError(currentParserLoc, "expect operand bundle tag");

  if (p.parseLParen())
    return failure();

  if (p.parseOptionalRParen()) {
    if (p.parseOperandList(operands) || p.parseColon() ||
        p.parseTypeList(types) || p.parseRParen())
      return failure();
  }

  opBundleOperands.push_back(std::move(operands));
  opBundleOperandTypes.push_back(std::move(types));
  opBundleTags.push_back(StringAttr::get(p.getContext(), tag));

  return success();
}

static std::optional<ParseResult> parseOpBundles(
    OpAsmParser &p,
    SmallVector<SmallVector<OpAsmParser::UnresolvedOperand>> &opBundleOperands,
    SmallVector<SmallVector<Type>> &opBundleOperandTypes,
    ArrayAttr &opBundleTags) {
  if (p.parseOptionalLSquare())
    return std::nullopt;

  if (succeeded(p.parseOptionalRSquare()))
    return success();

  SmallVector<Attribute> opBundleTagAttrs;
  auto bundleParser = [&] {
    return parseOneOpBundle(p, opBundleOperands, opBundleOperandTypes,
                            opBundleTagAttrs);
  };
  if (p.parseCommaSeparatedList(bundleParser))
    return failure();

  if (p.parseRSquare())
    return failure();

  opBundleTags = ArrayAttr::get(p.getContext(), opBundleTagAttrs);

  return success();
}

//===----------------------------------------------------------------------===//
// Printing, parsing, folding and builder for LLVM::CmpOp.
//===----------------------------------------------------------------------===//

void ICmpOp::print(OpAsmPrinter &p) {
  p << " \"" << stringifyICmpPredicate(getPredicate()) << "\" " << getOperand(0)
    << ", " << getOperand(1);
  p.printOptionalAttrDict((*this)->getAttrs(), {"predicate"});
  p << " : " << getLhs().getType();
}

void FCmpOp::print(OpAsmPrinter &p) {
  p << " \"" << stringifyFCmpPredicate(getPredicate()) << "\" " << getOperand(0)
    << ", " << getOperand(1);
  p.printOptionalAttrDict(processFMFAttr((*this)->getAttrs()), {"predicate"});
  p << " : " << getLhs().getType();
}

// <operation> ::= `llvm.icmp` string-literal ssa-use `,` ssa-use
//                 attribute-dict? `:` type
// <operation> ::= `llvm.fcmp` string-literal ssa-use `,` ssa-use
//                 attribute-dict? `:` type
template <typename CmpPredicateType>
static ParseResult parseCmpOp(OpAsmParser &parser, OperationState &result) {
  StringAttr predicateAttr;
  OpAsmParser::UnresolvedOperand lhs, rhs;
  Type type;
  SMLoc predicateLoc, trailingTypeLoc;
  if (parser.getCurrentLocation(&predicateLoc) ||
      parser.parseAttribute(predicateAttr, "predicate", result.attributes) ||
      parser.parseOperand(lhs) || parser.parseComma() ||
      parser.parseOperand(rhs) ||
      parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
      parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type) ||
      parser.resolveOperand(lhs, type, result.operands) ||
      parser.resolveOperand(rhs, type, result.operands))
    return failure();

  // Replace the string attribute `predicate` with an integer attribute.
  int64_t predicateValue = 0;
  if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
    std::optional<ICmpPredicate> predicate =
        symbolizeICmpPredicate(predicateAttr.getValue());
    if (!predicate)
      return parser.emitError(predicateLoc)
             << "'" << predicateAttr.getValue()
             << "' is an incorrect value of the 'predicate' attribute";
    predicateValue = static_cast<int64_t>(*predicate);
  } else {
    std::optional<FCmpPredicate> predicate =
        symbolizeFCmpPredicate(predicateAttr.getValue());
    if (!predicate)
      return parser.emitError(predicateLoc)
             << "'" << predicateAttr.getValue()
             << "' is an incorrect value of the 'predicate' attribute";
    predicateValue = static_cast<int64_t>(*predicate);
  }

  result.attributes.set("predicate",
                        parser.getBuilder().getI64IntegerAttr(predicateValue));

  // The result type is either i1 or a vector type <? x i1> if the inputs are
  // vectors.
  if (!isCompatibleType(type))
    return parser.emitError(trailingTypeLoc,
                            "expected LLVM dialect-compatible type");
  result.addTypes(getI1SameShape(type));
  return success();
}

ParseResult ICmpOp::parse(OpAsmParser &parser, OperationState &result) {
  return parseCmpOp<ICmpPredicate>(parser, result);
}

ParseResult FCmpOp::parse(OpAsmParser &parser, OperationState &result) {
  return parseCmpOp<FCmpPredicate>(parser, result);
}

/// Returns a scalar or vector boolean attribute of the given type.
static Attribute getBoolAttribute(Type type, MLIRContext *ctx, bool value) {
  auto boolAttr = BoolAttr::get(ctx, value);
  ShapedType shapedType = dyn_cast<ShapedType>(type);
  if (!shapedType)
    return boolAttr;
  return DenseElementsAttr::get(shapedType, boolAttr);
}

OpFoldResult ICmpOp::fold(FoldAdaptor adaptor) {
  if (getPredicate() != ICmpPredicate::eq &&
      getPredicate() != ICmpPredicate::ne)
    return {};

  // cmpi(eq/ne, x, x) -> true/false
  if (getLhs() == getRhs())
    return getBoolAttribute(getType(), getContext(),
                            getPredicate() == ICmpPredicate::eq);

  // cmpi(eq/ne, alloca, null) -> false/true
  if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
    return getBoolAttribute(getType(), getContext(),
                            getPredicate() == ICmpPredicate::ne);

  // cmpi(eq/ne, null, alloca) -> cmpi(eq/ne, alloca, null)
  if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
    Value lhs = getLhs();
    Value rhs = getRhs();
    getLhsMutable().assign(rhs);
    getRhsMutable().assign(lhs);
    return getResult();
  }

  return {};
}

//===----------------------------------------------------------------------===//
// Printing, parsing and verification for LLVM::AllocaOp.
//===----------------------------------------------------------------------===//

void AllocaOp::print(OpAsmPrinter &p) {
  auto funcTy =
      FunctionType::get(getContext(), {getArraySize().getType()}, {getType()});

  if (getInalloca())
    p << " inalloca";

  p << ' ' << getArraySize() << " x " << getElemType();
  if (getAlignment() && *getAlignment() != 0)
    p.printOptionalAttrDict((*this)->getAttrs(),
                            {kElemTypeAttrName, getInallocaAttrName()});
  else
    p.printOptionalAttrDict(
        (*this)->getAttrs(),
        {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
  p << " : " << funcTy;
}

// <operation> ::= `llvm.alloca` `inalloca`? ssa-use `x` type
//                  attribute-dict? `:` type `,` type
ParseResult AllocaOp::parse(OpAsmParser &parser, OperationState &result) {
  OpAsmParser::UnresolvedOperand arraySize;
  Type type, elemType;
  SMLoc trailingTypeLoc;

  if (succeeded(parser.parseOptionalKeyword("inalloca")))
    result.addAttribute(getInallocaAttrName(result.name),
                        UnitAttr::get(parser.getContext()));

  if (parser.parseOperand(arraySize) || parser.parseKeyword("x") ||
      parser.parseType(elemType) ||
      parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
      parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type))
    return failure();

  std::optional<NamedAttribute> alignmentAttr =
      result.attributes.getNamed("alignment");
  if (alignmentAttr.has_value()) {
    auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
    if (!alignmentInt)
      return parser.emitError(parser.getNameLoc(),
                              "expected integer alignment");
    if (alignmentInt.getValue().isZero())
      result.attributes.erase("alignment");
  }

  // Extract the result type from the trailing function type.
  auto funcType = llvm::dyn_cast<FunctionType>(type);
  if (!funcType || funcType.getNumInputs() != 1 ||
      funcType.getNumResults() != 1)
    return parser.emitError(
        trailingTypeLoc,
        "expected trailing function type with one argument and one result");

  if (parser.resolveOperand(arraySize, funcType.getInput(0), result.operands))
    return failure();

  Type resultType = funcType.getResult(0);
  if (auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
    result.addAttribute(kElemTypeAttrName, TypeAttr::get(elemType));

  result.addTypes({funcType.getResult(0)});
  return success();
}

LogicalResult AllocaOp::verify() {
  // Only certain target extension types can be used in 'alloca'.
  if (auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
      targetExtType && !targetExtType.supportsMemOps())
    return emitOpError()
           << "this target extension type cannot be used in alloca";

  return success();
}

//===----------------------------------------------------------------------===//
// LLVM::BrOp
//===----------------------------------------------------------------------===//

SuccessorOperands BrOp::getSuccessorOperands(unsigned index) {
  assert(index == 0 && "invalid successor index");
  return SuccessorOperands(getDestOperandsMutable());
}

//===----------------------------------------------------------------------===//
// LLVM::CondBrOp
//===----------------------------------------------------------------------===//

SuccessorOperands CondBrOp::getSuccessorOperands(unsigned index) {
  assert(index < getNumSuccessors() && "invalid successor index");
  return SuccessorOperands(index == 0 ? getTrueDestOperandsMutable()
                                      : getFalseDestOperandsMutable());
}

void CondBrOp::build(OpBuilder &builder, OperationState &result,
                     Value condition, Block *trueDest, ValueRange trueOperands,
                     Block *falseDest, ValueRange falseOperands,
                     std::optional<std::pair<uint32_t, uint32_t>> weights) {
  DenseI32ArrayAttr weightsAttr;
  if (weights)
    weightsAttr =
        builder.getDenseI32ArrayAttr({static_cast<int32_t>(weights->first),
                                      static_cast<int32_t>(weights->second)});

  build(builder, result, condition, trueOperands, falseOperands, weightsAttr,
        /*loop_annotation=*/{}, trueDest, falseDest);
}

//===----------------------------------------------------------------------===//
// LLVM::SwitchOp
//===----------------------------------------------------------------------===//

void SwitchOp::build(OpBuilder &builder, OperationState &result, Value value,
                     Block *defaultDestination, ValueRange defaultOperands,
                     DenseIntElementsAttr caseValues,
                     BlockRange caseDestinations,
                     ArrayRef<ValueRange> caseOperands,
                     ArrayRef<int32_t> branchWeights) {
  DenseI32ArrayAttr weightsAttr;
  if (!branchWeights.empty())
    weightsAttr = builder.getDenseI32ArrayAttr(branchWeights);

  build(builder, result, value, defaultOperands, caseOperands, caseValues,
        weightsAttr, defaultDestination, caseDestinations);
}

void SwitchOp::build(OpBuilder &builder, OperationState &result, Value value,
                     Block *defaultDestination, ValueRange defaultOperands,
                     ArrayRef<APInt> caseValues, BlockRange caseDestinations,
                     ArrayRef<ValueRange> caseOperands,
                     ArrayRef<int32_t> branchWeights) {
  DenseIntElementsAttr caseValuesAttr;
  if (!caseValues.empty()) {
    ShapedType caseValueType = VectorType::get(
        static_cast<int64_t>(caseValues.size()), value.getType());
    caseValuesAttr = DenseIntElementsAttr::get(caseValueType, caseValues);
  }

  build(builder, result, value, defaultDestination, defaultOperands,
        caseValuesAttr, caseDestinations, caseOperands, branchWeights);
}

void SwitchOp::build(OpBuilder &builder, OperationState &result, Value value,
                     Block *defaultDestination, ValueRange defaultOperands,
                     ArrayRef<int32_t> caseValues, BlockRange caseDestinations,
                     ArrayRef<ValueRange> caseOperands,
                     ArrayRef<int32_t> branchWeights) {
  DenseIntElementsAttr caseValuesAttr;
  if (!caseValues.empty()) {
    ShapedType caseValueType = VectorType::get(
        static_cast<int64_t>(caseValues.size()), value.getType());
    caseValuesAttr = DenseIntElementsAttr::get(caseValueType, caseValues);
  }

  build(builder, result, value, defaultDestination, defaultOperands,
        caseValuesAttr, caseDestinations, caseOperands, branchWeights);
}

/// <cases> ::= `[` (case (`,` case )* )? `]`
/// <case>  ::= integer `:` bb-id (`(` ssa-use-and-type-list `)`)?
static ParseResult parseSwitchOpCases(
    OpAsmParser &parser, Type flagType, DenseIntElementsAttr &caseValues,
    SmallVectorImpl<Block *> &caseDestinations,
    SmallVectorImpl<SmallVector<OpAsmParser::UnresolvedOperand>> &caseOperands,
    SmallVectorImpl<SmallVector<Type>> &caseOperandTypes) {
  if (failed(parser.parseLSquare()))
    return failure();
  if (succeeded(parser.parseOptionalRSquare()))
    return success();
  SmallVector<APInt> values;
  unsigned bitWidth = flagType.getIntOrFloatBitWidth();
  auto parseCase = [&]() {
    int64_t value = 0;
    if (failed(parser.parseInteger(value)))
      return failure();
    values.push_back(APInt(bitWidth, value, /*isSigned=*/true));

    Block *destination;
    SmallVector<OpAsmParser::UnresolvedOperand> operands;
    SmallVector<Type> operandTypes;
    if (parser.parseColon() || parser.parseSuccessor(destination))
      return failure();
    if (!parser.parseOptionalLParen()) {
      if (parser.parseOperandList(operands, OpAsmParser::Delimiter::None,
                                  /*allowResultNumber=*/false) ||
          parser.parseColonTypeList(operandTypes) || parser.parseRParen())
        return failure();
    }
    caseDestinations.push_back(destination);
    caseOperands.emplace_back(operands);
    caseOperandTypes.emplace_back(operandTypes);
    return success();
  };
  if (failed(parser.parseCommaSeparatedList(parseCase)))
    return failure();

  ShapedType caseValueType =
      VectorType::get(static_cast<int64_t>(values.size()), flagType);
  caseValues = DenseIntElementsAttr::get(caseValueType, values);
  return parser.parseRSquare();
}

static void printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type flagType,
                               DenseIntElementsAttr caseValues,
                               SuccessorRange caseDestinations,
                               OperandRangeRange caseOperands,
                               const TypeRangeRange &caseOperandTypes) {
  p << '[';
  p.printNewline();
  if (!caseValues) {
    p << ']';
    return;
  }

  size_t index = 0;
  llvm::interleave(
      llvm::zip(caseValues, caseDestinations),
      [&](auto i) {
        p << "  ";
        p << std::get<0>(i);
        p << ": ";
        p.printSuccessorAndUseList(std::get<1>(i), caseOperands[index++]);
      },
      [&] {
        p << ',';
        p.printNewline();
      });
  p.printNewline();
  p << ']';
}

LogicalResult SwitchOp::verify() {
  if ((!getCaseValues() && !getCaseDestinations().empty()) ||
      (getCaseValues() &&
       getCaseValues()->size() !=
           static_cast<int64_t>(getCaseDestinations().size())))
    return emitOpError("expects number of case values to match number of "
                       "case destinations");
  if (getCaseValues() &&
      getValue().getType() != getCaseValues()->getElementType())
    return emitError("expects case value type to match condition value type");
  return success();
}

SuccessorOperands SwitchOp::getSuccessorOperands(unsigned index) {
  assert(index < getNumSuccessors() && "invalid successor index");
  return SuccessorOperands(index == 0 ? getDefaultOperandsMutable()
                                      : getCaseOperandsMutable(index - 1));
}

//===----------------------------------------------------------------------===//
// Code for LLVM::GEPOp.
//===----------------------------------------------------------------------===//

GEPIndicesAdaptor<ValueRange> GEPOp::getIndices() {
  return GEPIndicesAdaptor<ValueRange>(getRawConstantIndicesAttr(),
                                       getDynamicIndices());
}

/// Returns the elemental type of any LLVM-compatible vector type or self.
static Type extractVectorElementType(Type type) {
  if (auto vectorType = llvm::dyn_cast<VectorType>(type))
    return vectorType.getElementType();
  return type;
}

/// Destructures the 'indices' parameter into 'rawConstantIndices' and
/// 'dynamicIndices', encoding the former in the process. In the process,
/// dynamic indices which are used to index into a structure type are converted
/// to constant indices when possible. To do this, the GEPs element type should
/// be passed as first parameter.
static void destructureIndices(Type currType, ArrayRef<GEPArg> indices,
                               SmallVectorImpl<int32_t> &rawConstantIndices,
                               SmallVectorImpl<Value> &dynamicIndices) {
  for (const GEPArg &iter : indices) {
    // If the thing we are currently indexing into is a struct we must turn
    // any integer constants into constant indices. If this is not possible
    // we don't do anything here. The verifier will catch it and emit a proper
    // error. All other canonicalization is done in the fold method.
    bool requiresConst = !rawConstantIndices.empty() &&
                         isa_and_nonnull<LLVMStructType>(currType);
    if (Value val = llvm::dyn_cast_if_present<Value>(iter)) {
      APInt intC;
      if (requiresConst && matchPattern(val, m_ConstantInt(&intC)) &&
          intC.isSignedIntN(kGEPConstantBitWidth)) {
        rawConstantIndices.push_back(intC.getSExtValue());
      } else {
        rawConstantIndices.push_back(GEPOp::kDynamicIndex);
        dynamicIndices.push_back(val);
      }
    } else {
      rawConstantIndices.push_back(cast<GEPConstantIndex>(iter));
    }

    // Skip for very first iteration of this loop. First index does not index
    // within the aggregates, but is just a pointer offset.
    if (rawConstantIndices.size() == 1 || !currType)
      continue;

    currType = TypeSwitch<Type, Type>(currType)
                   .Case<VectorType, LLVMArrayType>([](auto containerType) {
                     return containerType.getElementType();
                   })
                   .Case([&](LLVMStructType structType) -> Type {
                     int64_t memberIndex = rawConstantIndices.back();
                     if (memberIndex >= 0 && static_cast<size_t>(memberIndex) <
                                                 structType.getBody().size())
                       return structType.getBody()[memberIndex];
                     return nullptr;
                   })
                   .Default(nullptr);
  }
}

void GEPOp::build(OpBuilder &builder, OperationState &result, Type resultType,
                  Type elementType, Value basePtr, ArrayRef<GEPArg> indices,
                  GEPNoWrapFlags noWrapFlags,
                  ArrayRef<NamedAttribute> attributes) {
  SmallVector<int32_t> rawConstantIndices;
  SmallVector<Value> dynamicIndices;
  destructureIndices(elementType, indices, rawConstantIndices, dynamicIndices);

  result.addTypes(resultType);
  result.addAttributes(attributes);
  result.getOrAddProperties<Properties>().rawConstantIndices =
      builder.getDenseI32ArrayAttr(rawConstantIndices);
  result.getOrAddProperties<Properties>().noWrapFlags = noWrapFlags;
  result.getOrAddProperties<Properties>().elem_type =
      TypeAttr::get(elementType);
  result.addOperands(basePtr);
  result.addOperands(dynamicIndices);
}

void GEPOp::build(OpBuilder &builder, OperationState &result, Type resultType,
                  Type elementType, Value basePtr, ValueRange indices,
                  GEPNoWrapFlags noWrapFlags,
                  ArrayRef<NamedAttribute> attributes) {
  build(builder, result, resultType, elementType, basePtr,
        SmallVector<GEPArg>(indices), noWrapFlags, attributes);
}

static ParseResult
parseGEPIndices(OpAsmParser &parser,
                SmallVectorImpl<OpAsmParser::UnresolvedOperand> &indices,
                DenseI32ArrayAttr &rawConstantIndices) {
  SmallVector<int32_t> constantIndices;

  auto idxParser = [&]() -> ParseResult {
    int32_t constantIndex;
    OptionalParseResult parsedInteger =
        parser.parseOptionalInteger(constantIndex);
    if (parsedInteger.has_value()) {
      if (failed(parsedInteger.value()))
        return failure();
      constantIndices.push_back(constantIndex);
      return success();
    }

    constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
    return parser.parseOperand(indices.emplace_back());
  };
  if (parser.parseCommaSeparatedList(idxParser))
    return failure();

  rawConstantIndices =
      DenseI32ArrayAttr::get(parser.getContext(), constantIndices);
  return success();
}

static void printGEPIndices(OpAsmPrinter &printer, LLVM::GEPOp gepOp,
                            OperandRange indices,
                            DenseI32ArrayAttr rawConstantIndices) {
  llvm::interleaveComma(
      GEPIndicesAdaptor<OperandRange>(rawConstantIndices, indices), printer,
      [&](PointerUnion<IntegerAttr, Value> cst) {
        if (Value val = llvm::dyn_cast_if_present<Value>(cst))
          printer.printOperand(val);
        else
          printer << cast<IntegerAttr>(cst).getInt();
      });
}

/// For the given `indices`, check if they comply with `baseGEPType`,
/// especially check against LLVMStructTypes nested within.
static LogicalResult
verifyStructIndices(Type baseGEPType, unsigned indexPos,
                    GEPIndicesAdaptor<ValueRange> indices,
                    function_ref<InFlightDiagnostic()> emitOpError) {
  if (indexPos >= indices.size())
    // Stop searching
    return success();

  return TypeSwitch<Type, LogicalResult>(baseGEPType)
      .Case([&](LLVMStructType structType) -> LogicalResult {
        auto attr = dyn_cast<IntegerAttr>(indices[indexPos]);
        if (!attr)
          return emitOpError() << "expected index " << indexPos
                               << " indexing a struct to be constant";

        int32_t gepIndex = attr.getInt();
        ArrayRef<Type> elementTypes = structType.getBody();
        if (gepIndex < 0 ||
            static_cast<size_t>(gepIndex) >= elementTypes.size())
          return emitOpError() << "index " << indexPos
                               << " indexing a struct is out of bounds";

        // Instead of recursively going into every children types, we only
        // dive into the one indexed by gepIndex.
        return verifyStructIndices(elementTypes[gepIndex], indexPos + 1,
                                   indices, emitOpError);
      })
      .Case<VectorType, LLVMArrayType>(
          [&](auto containerType) -> LogicalResult {
            return verifyStructIndices(containerType.getElementType(),
                                       indexPos + 1, indices, emitOpError);
          })
      .Default([&](auto otherType) -> LogicalResult {
        return emitOpError()
               << "type " << otherType << " cannot be indexed (index #"
               << indexPos << ")";
      });
}

/// Driver function around `verifyStructIndices`.
static LogicalResult
verifyStructIndices(Type baseGEPType, GEPIndicesAdaptor<ValueRange> indices,
                    function_ref<InFlightDiagnostic()> emitOpError) {
  return verifyStructIndices(baseGEPType, /*indexPos=*/1, indices, emitOpError);
}

LogicalResult LLVM::GEPOp::verify() {
  if (static_cast<size_t>(
          llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
      getDynamicIndices().size())
    return emitOpError("expected as many dynamic indices as specified in '")
           << getRawConstantIndicesAttrName().getValue() << "'";

  if (getNoWrapFlags() == GEPNoWrapFlags::inboundsFlag)
    return emitOpError("'inbounds_flag' cannot be used directly.");

  return verifyStructIndices(getElemType(), getIndices(),
                             [&] { return emitOpError(); });
}

//===----------------------------------------------------------------------===//
// LoadOp
//===----------------------------------------------------------------------===//

void LoadOp::getEffects(
    SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
        &effects) {
  effects.emplace_back(MemoryEffects::Read::get(), &getAddrMutable());
  // Volatile operations can have target-specific read-write effects on
  // memory besides the one referred to by the pointer operand.
  // Similarly, atomic operations that are monotonic or stricter cause
  // synchronization that from a language point-of-view, are arbitrary
  // read-writes into memory.
  if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
                         getOrdering() != AtomicOrdering::unordered)) {
    effects.emplace_back(MemoryEffects::Write::get());
    effects.emplace_back(MemoryEffects::Read::get());
  }
}

/// Returns true if the given type is supported by atomic operations. All
/// integer, float, and pointer types with a power-of-two bitsize and a minimal
/// size of 8 bits are supported.
bool LLVM::isTypeCompatibleWithAtomicOp(Type type,
                                        const DataLayout &dataLayout) {
  if (!isa<IntegerType, LLVMPointerType>(type))
    if (!isCompatibleFloatingPointType(type))
      return false;

  llvm::TypeSize bitWidth = dataLayout.getTypeSizeInBits(type);
  if (bitWidth.isScalable())
    return false;
  // Needs to be at least 8 bits and a power of two.
  return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
}

/// Verifies the attributes and the type of atomic memory access operations.
template <typename OpTy>
static LogicalResult
verifyAtomicMemOp(OpTy memOp, Type valueType,
                  ArrayRef<AtomicOrdering> unsupportedOrderings) {
  if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
    DataLayout dataLayout = DataLayout::closest(memOp);
    if (!isTypeCompatibleWithAtomicOp(valueType, dataLayout))
      return memOp.emitOpError("unsupported type ")
             << valueType << " for atomic access";
    if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
      return memOp.emitOpError("unsupported ordering '")
             << stringifyAtomicOrdering(memOp.getOrdering()) << "'";
    if (!memOp.getAlignment())
      return memOp.emitOpError("expected alignment for atomic access");
    return success();
  }
  if (memOp.getSyncscope())
    return memOp.emitOpError(
        "expected syncscope to be null for non-atomic access");
  return success();
}

LogicalResult LoadOp::verify() {
  Type valueType = getResult().getType();
  return verifyAtomicMemOp(*this, valueType,
                           {AtomicOrdering::release, AtomicOrdering::acq_rel});
}

void LoadOp::build(OpBuilder &builder, OperationState &state, Type type,
                   Value addr, unsigned alignment, bool isVolatile,
                   bool isNonTemporal, bool isInvariant, bool isInvariantGroup,
                   AtomicOrdering ordering, StringRef syncscope) {
  build(builder, state, type, addr,
        alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isVolatile,
        isNonTemporal, isInvariant, isInvariantGroup, ordering,
        syncscope.empty() ? nullptr : builder.getStringAttr(syncscope),
        /*dereferenceable=*/nullptr,
        /*access_groups=*/nullptr,
        /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr,
        /*tbaa=*/nullptr);
}

//===----------------------------------------------------------------------===//
// StoreOp
//===----------------------------------------------------------------------===//

void StoreOp::getEffects(
    SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
        &effects) {
  effects.emplace_back(MemoryEffects::Write::get(), &getAddrMutable());
  // Volatile operations can have target-specific read-write effects on
  // memory besides the one referred to by the pointer operand.
  // Similarly, atomic operations that are monotonic or stricter cause
  // synchronization that from a language point-of-view, are arbitrary
  // read-writes into memory.
  if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
                         getOrdering() != AtomicOrdering::unordered)) {
    effects.emplace_back(MemoryEffects::Write::get());
    effects.emplace_back(MemoryEffects::Read::get());
  }
}

LogicalResult StoreOp::verify() {
  Type valueType = getValue().getType();
  return verifyAtomicMemOp(*this, valueType,
                           {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
}

void StoreOp::build(OpBuilder &builder, OperationState &state, Value value,
                    Value addr, unsigned alignment, bool isVolatile,
                    bool isNonTemporal, bool isInvariantGroup,
                    AtomicOrdering ordering, StringRef syncscope) {
  build(builder, state, value, addr,
        alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isVolatile,
        isNonTemporal, isInvariantGroup, ordering,
        syncscope.empty() ? nullptr : builder.getStringAttr(syncscope),
        /*access_groups=*/nullptr,
        /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
}

//===----------------------------------------------------------------------===//
// CallOp
//===----------------------------------------------------------------------===//

/// Gets the MLIR Op-like result types of a LLVMFunctionType.
static SmallVector<Type, 1> getCallOpResultTypes(LLVMFunctionType calleeType) {
  SmallVector<Type, 1> results;
  Type resultType = calleeType.getReturnType();
  if (!isa<LLVM::LLVMVoidType>(resultType))
    results.push_back(resultType);
  return results;
}

/// Gets the variadic callee type for a LLVMFunctionType.
static TypeAttr getCallOpVarCalleeType(LLVMFunctionType calleeType) {
  return calleeType.isVarArg() ? TypeAttr::get(calleeType) : nullptr;
}

/// Constructs a LLVMFunctionType from MLIR `results` and `args`.
static LLVMFunctionType getLLVMFuncType(MLIRContext *context, TypeRange results,
                                        ValueRange args) {
  Type resultType;
  if (results.empty())
    resultType = LLVMVoidType::get(context);
  else
    resultType = results.front();
  return LLVMFunctionType::get(resultType, llvm::to_vector(args.getTypes()),
                               /*isVarArg=*/false);
}

void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results,
                   StringRef callee, ValueRange args) {
  build(builder, state, results, builder.getStringAttr(callee), args);
}

void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results,
                   StringAttr callee, ValueRange args) {
  build(builder, state, results, SymbolRefAttr::get(callee), args);
}

void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results,
                   FlatSymbolRefAttr callee, ValueRange args) {
  assert(callee && "expected non-null callee in direct call builder");
  build(builder, state, results,
        /*var_callee_type=*/nullptr, callee, args, /*fastmathFlags=*/nullptr,
        /*CConv=*/nullptr, /*TailCallKind=*/nullptr,
        /*memory_effects=*/nullptr,
        /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
        /*noreturn=*/nullptr, /*returns_twice=*/nullptr, /*hot=*/nullptr,
        /*cold=*/nullptr, /*noduplicate=*/nullptr,
        /*no_caller_saved_registers=*/nullptr, /*nocallback=*/nullptr,
        /*modular_format=*/nullptr, /*nobuiltins=*/nullptr,
        /*allocsize=*/nullptr, /*optsize=*/nullptr, /*minsize=*/nullptr,
        /*builtin=*/nullptr, /*nobuiltin=*/nullptr,
        /*save_reg_params=*/nullptr,
        /*zero_call_used_regs=*/nullptr, /*trap_func_name=*/nullptr,
        /*default_func_attrs=*/nullptr,
        /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
        /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
        /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
        /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr,
        /*no_inline=*/nullptr, /*always_inline=*/nullptr,
        /*inline_hint=*/nullptr);
}

void CallOp::build(OpBuilder &builder, OperationState &state,
                   LLVMFunctionType calleeType, StringRef callee,
                   ValueRange args) {
  build(builder, state, calleeType, builder.getStringAttr(callee), args);
}

void CallOp::build(OpBuilder &builder, OperationState &state,
                   LLVMFunctionType calleeType, StringAttr callee,
                   ValueRange args) {
  build(builder, state, calleeType, SymbolRefAttr::get(callee), args);
}

void CallOp::build(OpBuilder &builder, OperationState &state,
                   LLVMFunctionType calleeType, FlatSymbolRefAttr callee,
                   ValueRange args) {
  build(builder, state, getCallOpResultTypes(calleeType),
        getCallOpVarCalleeType(calleeType), callee, args,
        /*fastmathFlags=*/nullptr,
        /*CConv=*/nullptr,
        /*TailCallKind=*/nullptr, /*memory_effects=*/nullptr,
        /*convergent=*/nullptr,
        /*no_unwind=*/nullptr, /*will_return=*/nullptr,
        /*noreturn=*/nullptr,
        /*returns_twice=*/nullptr, /*hot=*/nullptr,
        /*cold=*/nullptr, /*noduplicate=*/nullptr,
        /*no_caller_saved_registers=*/nullptr, /*nocallback=*/nullptr,
        /*modular_format=*/nullptr, /*nobuiltins=*/nullptr,
        /*allocsize=*/nullptr, /*optsize=*/nullptr, /*minsize=*/nullptr,
        /*builtin=*/nullptr, /*nobuiltin=*/nullptr,
        /*save_reg_params=*/nullptr,
        /*zero_call_used_regs=*/nullptr, /*trap_func_name=*/nullptr,
        /*default_func_attrs=*/nullptr,
        /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
        /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
        /*access_groups=*/nullptr,
        /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr,
        /*no_inline=*/nullptr, /*always_inline=*/nullptr,
        /*inline_hint=*/nullptr);
}

void CallOp::build(OpBuilder &builder, OperationState &state,
                   LLVMFunctionType calleeType, ValueRange args) {
  build(builder, state, getCallOpResultTypes(calleeType),
        getCallOpVarCalleeType(calleeType),
        /*callee=*/nullptr, args,
        /*fastmathFlags=*/nullptr,
        /*CConv=*/nullptr, /*TailCallKind=*/nullptr, /*memory_effects=*/nullptr,
        /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
        /*noreturn=*/nullptr,
        /*returns_twice=*/nullptr, /*hot=*/nullptr,
        /*cold=*/nullptr, /*noduplicate=*/nullptr,
        /*no_caller_saved_registers=*/nullptr, /*nocallback=*/nullptr,
        /*modular_format=*/nullptr, /*nobuiltins=*/nullptr,
        /*allocsize=*/nullptr, /*optsize=*/nullptr, /*minsize=*/nullptr,
        /*builtin=*/nullptr, /*nobuiltin=*/nullptr,
        /*save_reg_params=*/nullptr,
        /*zero_call_used_regs=*/nullptr, /*trap_func_name=*/nullptr,
        /*default_func_attrs=*/nullptr,
        /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
        /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
        /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
        /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr,
        /*no_inline=*/nullptr, /*always_inline=*/nullptr,
        /*inline_hint=*/nullptr);
}

void CallOp::build(OpBuilder &builder, OperationState &state, LLVMFuncOp func,
                   ValueRange args) {
  auto calleeType = func.getFunctionType();
  build(builder, state, getCallOpResultTypes(calleeType),
        getCallOpVarCalleeType(calleeType), SymbolRefAttr::get(func), args,
        /*fastmathFlags=*/nullptr,
        /*CConv=*/nullptr, /*TailCallKind=*/nullptr, /*memory_effects=*/nullptr,
        /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
        /*noreturn=*/nullptr,
        /*returns_twice=*/nullptr, /*hot=*/nullptr,
        /*cold=*/nullptr, /*noduplicate=*/nullptr,
        /*no_caller_saved_registers=*/nullptr, /*nocallback=*/nullptr,
        /*modular_format=*/nullptr, /*nobuiltins=*/nullptr,
        /*allocsize=*/nullptr, /*optsize=*/nullptr, /*minsize=*/nullptr,
        /*builtin=*/nullptr, /*nobuiltin=*/nullptr,
        /*save_reg_params=*/nullptr,
        /*zero_call_used_regs=*/nullptr, /*trap_func_name=*/nullptr,
        /*default_func_attrs=*/nullptr,
        /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
        /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
        /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
        /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr,
        /*no_inline=*/nullptr, /*always_inline=*/nullptr,
        /*inline_hint=*/nullptr);
}

CallInterfaceCallable CallOp::getCallableForCallee() {
  // Direct call.
  if (FlatSymbolRefAttr calleeAttr = getCalleeAttr())
    return calleeAttr;
  // Indirect call, callee Value is the first operand.
  return getOperand(0);
}

void CallOp::setCalleeFromCallable(CallInterfaceCallable callee) {
  // Direct call.
  if (FlatSymbolRefAttr calleeAttr = getCalleeAttr()) {
    auto symRef = cast<SymbolRefAttr>(callee);
    return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
  }
  // Indirect call, callee Value is the first operand.
  return setOperand(0, cast<Value>(callee));
}

/// Return the number of leading callee operands of `callOp` that the operation
/// consumes instead of passing them to the callee.
template <typename OpTy>
static unsigned getNumConsumedCalleeOperands(OpTy callOp) {
  // The first operand is the callee if no callee attribute is present.
  if (callOp.getCallee().has_value())
    return 0;
  return 1;
}

/// Return the operands of `callOp` that are passed to the callee, including the
/// variadic arguments in case of a call to a variadic callee.
template <typename OpTy>
static Operation::operand_range getOperandsPassedToCallee(OpTy callOp) {
  return callOp.getCalleeOperands().drop_front(
      getNumConsumedCalleeOperands(callOp));
}

/// Return the operands of `callOp` that correspond to the declared parameters
/// of the callee, i.e., its `CallOpInterface` argument operands.
///
/// The variadic arguments of a call to a variadic callee are *not* included:
/// they do not correspond to any argument of the callee. The callee does not
/// receive them as block arguments but reads them with `llvm.intr.vastart` and
/// friends, so in terms of `CallOpInterface` they are consumed operands rather
/// than forwarded ones.
template <typename OpTy>
static Operation::operand_range getArgOperandsImpl(OpTy callOp) {
  Operation::operand_range operands = getOperandsPassedToCallee(callOp);
  if (std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType())
    return operands.take_front(varCalleeType->getNumParams());
  return operands;
}

Operation::operand_range CallOp::getArgOperands() {
  return getArgOperandsImpl(*this);
}

MutableOperandRange CallOp::getArgOperandsMutable() {
  return MutableOperandRange(*this, getNumConsumedCalleeOperands(*this),
                             getArgOperandsImpl(*this).size());
}

/// Verify that an inlinable callsite of a debug-info-bearing function in a
/// debug-info-bearing function has a debug location attached to it. This
/// mirrors an LLVM IR verifier.
static LogicalResult verifyCallOpDebugInfo(CallOp callOp, LLVMFuncOp callee) {
  if (callee.isExternal())
    return success();
  auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
  if (!parentFunc)
    return success();

  auto hasSubprogram = [](Operation *op) {
    return op->getLoc()
               ->findInstanceOf<FusedLocWith<LLVM::DISubprogramAttr>>() !=
           nullptr;
  };
  if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
    return success();
  bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
  if (!containsLoc)
    return callOp.emitError()
           << "inlinable function call in a function with a DISubprogram "
              "location must have a debug location";
  return success();
}

/// Verify that the parameter and return types of the variadic callee type match
/// the `callOp` argument and result types.
template <typename OpTy>
static LogicalResult verifyCallOpVarCalleeType(OpTy callOp) {
  // An indirect call stores the callee in its first callee operand.
  if (!callOp.getCallee().has_value() && callOp.getCalleeOperands().empty())
    return callOp.emitOpError(
        "must have either a `callee` attribute or at least an operand");

  std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
  if (!varCalleeType)
    return success();

  // Verify the variadic callee type is a variadic function type.
  if (!varCalleeType->isVarArg())
    return callOp.emitOpError(
        "expected var_callee_type to be a variadic function type");

  // Note: `getArgOperands` is derived from `var_callee_type`, so the raw callee
  // operands are used here instead.
  Operation::operand_range passedOperands = getOperandsPassedToCallee(callOp);

  // Verify the variadic callee type has at most as many parameters as the call
  // has argument operands.
  if (varCalleeType->getNumParams() > passedOperands.size())
    return callOp.emitOpError("expected var_callee_type to have at most ")
           << passedOperands.size() << " parameters";

  // Verify the variadic callee type matches the call argument types.
  for (auto [paramType, operand] :
       llvm::zip(varCalleeType->getParams(), passedOperands))
    if (paramType != operand.getType())
      return callOp.emitOpError()
             << "var_callee_type parameter type mismatch: " << paramType
             << " != " << operand.getType();

  // Verify the variadic callee type matches the call result type.
  if (!callOp.getNumResults()) {
    if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
      return callOp.emitOpError("expected var_callee_type to return void");
  } else {
    if (callOp.getResult().getType() != varCalleeType->getReturnType())
      return callOp.emitOpError("var_callee_type return type mismatch: ")
             << varCalleeType->getReturnType()
             << " != " << callOp.getResult().getType();
  }
  return success();
}

template <typename OpType>
static LogicalResult verifyOperandBundles(OpType &op) {
  OperandRangeRange opBundleOperands = op.getOpBundleOperands();
  std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();

  auto isStringAttr = [](Attribute tagAttr) {
    return isa<StringAttr>(tagAttr);
  };
  if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
    return op.emitError("operand bundle tag must be a StringAttr");

  size_t numOpBundles = opBundleOperands.size();
  size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
  if (numOpBundles != numOpBundleTags)
    return op.emitError("expected ")
           << numOpBundles << " operand bundle tags, but actually got "
           << numOpBundleTags;

  return success();
}

LogicalResult CallOp::verify() { return verifyOperandBundles(*this); }

LogicalResult CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
  if (failed(verifyCallOpVarCalleeType(*this)))
    return failure();

  // Type for the callee, we'll get it differently depending if it is a direct
  // or indirect call.
  Type fnType;

  // If this is an indirect call, the callee attribute is missing.
  FlatSymbolRefAttr calleeName = getCalleeAttr();
  if (!calleeName) {
    // Note: `verifyCallOpVarCalleeType` has already checked that there is a
    // callee operand.
    auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).getType());
    if (!ptrType)
      return emitOpError("indirect call expects a pointer as callee: ")
             << getOperand(0).getType();

    // Nothing else to verify: an indirect callee cannot be resolved.
    return success();
  } else {
    Operation *callee =
        symbolTable.lookupNearestSymbolFrom(*this, calleeName.getAttr());
    if (!callee)
      return emitOpError()
             << "'" << calleeName.getValue()
             << "' does not reference a symbol in the current scope";
    if (auto fn = dyn_cast<LLVMFuncOp>(callee)) {
      if (failed(verifyCallOpDebugInfo(*this, fn)))
        return failure();
      fnType = fn.getFunctionType();
    } else if (auto ifunc = dyn_cast<IFuncOp>(callee)) {
      fnType = ifunc.getIFuncType();
    } else if (isa<AliasOp>(callee)) {
      // Aliases can alias functions, so calling through an alias is valid.
      // The function type is determined by the call's operands and result
      // types.
      fnType = getCalleeFunctionType();
    } else {
      return emitOpError()
             << "'" << calleeName.getValue()
             << "' does not reference a valid LLVM function, IFunc, or alias";
    }
  }

  LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
  if (!funcType)
    return emitOpError("callee does not have a functional type: ") << fnType;

  if (funcType.isVarArg() && !getVarCalleeType())
    return emitOpError() << "missing var_callee_type attribute for vararg call";

  // Verify the result types. These checks are more specific than what
  // `verifyCallOpInterface` can report, so they are run first.
  if (getNumResults() == 0 &&
      !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
    return emitOpError() << "expected function call to produce a value";

  if (getNumResults() != 0 &&
      llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
    return emitOpError()
           << "calling function with void result must not produce values";

  if (getNumResults() > 1)
    return emitOpError()
           << "expected LLVM function call to produce 0 or 1 result";

  if (getNumResults() && getResult().getType() != funcType.getReturnType())
    return emitOpError() << "result type mismatch: " << getResult().getType()
                         << " != " << funcType.getReturnType();

  // Verify that the operand types match the callee. Note that this does not
  // need to special-case a variadic callee: the variadic arguments are not
  // argument operands.
  SmallVector<Type, 1> calleeResultTypes;
  if (!llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
    calleeResultTypes.push_back(funcType.getReturnType());
  return call_interface_impl::verifyCallOpInterface(*this, funcType.getParams(),
                                                    calleeResultTypes);
}

void CallOp::print(OpAsmPrinter &p) {
  auto callee = getCallee();
  bool isDirect = callee.has_value();

  p << ' ';

  // Print calling convention.
  if (getCConv() != LLVM::CConv::C)
    p << stringifyCConv(getCConv()) << ' ';

  if (getTailCallKind() != LLVM::TailCallKind::None)
    p << tailcallkind::stringifyTailCallKind(getTailCallKind()) << ' ';

  // Print the direct callee if present as a function attribute, or an indirect
  // callee (first operand) otherwise.
  if (isDirect)
    p.printSymbolName(callee.value());
  else
    p << getOperand(0);

  auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
  p << '(' << args << ')';

  // Print the variadic callee type if the call is variadic.
  if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
    p << " vararg(" << *varCalleeType << ")";

  if (!getOpBundleOperands().empty()) {
    p << " ";
    printOpBundles(p, *this, getOpBundleOperands(),
                   getOpBundleOperands().getTypes(), getOpBundleTags());
  }

  p.printOptionalAttrDict(processFMFAttr((*this)->getAttrs()),
                          {getCalleeAttrName(), getTailCallKindAttrName(),
                           getVarCalleeTypeAttrName(), getCConvAttrName(),
                           getOperandSegmentSizesAttrName(),
                           getOpBundleSizesAttrName(),
                           getOpBundleTagsAttrName(), getArgAttrsAttrName(),
                           getResAttrsAttrName()});

  p << " : ";
  if (!isDirect)
    p << getOperand(0).getType() << ", ";

  // Reconstruct the MLIR function type from operand and result types.
  call_interface_impl::printFunctionSignature(
      p, args.getTypes(), getArgAttrsAttr(),
      /*isVariadic=*/false, getResultTypes(), getResAttrsAttr());
}

/// Parses the type of a call operation and resolves the operands if the parsing
/// succeeds. Returns failure otherwise.
static ParseResult parseCallTypeAndResolveOperands(
    OpAsmParser &parser, OperationState &result, bool isDirect,
    ArrayRef<OpAsmParser::UnresolvedOperand> operands,
    SmallVectorImpl<DictionaryAttr> &argAttrs,
    SmallVectorImpl<DictionaryAttr> &resultAttrs) {
  SMLoc trailingTypesLoc = parser.getCurrentLocation();
  SmallVector<Type> types;
  if (parser.parseColon())
    return failure();
  if (!isDirect) {
    types.emplace_back();
    if (parser.parseType(types.back()))
      return failure();
    if (parser.parseOptionalComma())
      return parser.emitError(
          trailingTypesLoc, "expected indirect call to have 2 trailing types");
  }
  SmallVector<Type> argTypes;
  SmallVector<Type> resTypes;
  if (call_interface_impl::parseFunctionSignature(parser, argTypes, argAttrs,
                                                  resTypes, resultAttrs)) {
    if (isDirect)
      return parser.emitError(trailingTypesLoc,
                              "expected direct call to have 1 trailing types");
    return parser.emitError(trailingTypesLoc,
                            "expected trailing function type");
  }

  if (resTypes.size() > 1)
    return parser.emitError(trailingTypesLoc,
                            "expected function with 0 or 1 result");
  if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
    return parser.emitError(trailingTypesLoc,
                            "expected a non-void result type");

  // The head element of the types list matches the callee type for
  // indirect calls, while the types list is emtpy for direct calls.
  // Append the function input types to resolve the call operation
  // operands.
  llvm::append_range(types, argTypes);
  if (parser.resolveOperands(operands, types, parser.getNameLoc(),
                             result.operands))
    return failure();
  if (!resTypes.empty())
    result.addTypes(resTypes);

  return success();
}

/// Parses an optional function pointer operand before the call argument list
/// for indirect calls, or stops parsing at the function identifier otherwise.
static ParseResult parseOptionalCallFuncPtr(
    OpAsmParser &parser,
    SmallVectorImpl<OpAsmParser::UnresolvedOperand> &operands) {
  OpAsmParser::UnresolvedOperand funcPtrOperand;
  OptionalParseResult parseResult = parser.parseOptionalOperand(funcPtrOperand);
  if (parseResult.has_value()) {
    if (failed(*parseResult))
      return *parseResult;
    operands.push_back(funcPtrOperand);
  }
  return success();
}

static ParseResult resolveOpBundleOperands(
    OpAsmParser &parser, SMLoc loc, OperationState &state,
    ArrayRef<SmallVector<OpAsmParser::UnresolvedOperand>> opBundleOperands,
    ArrayRef<SmallVector<Type>> opBundleOperandTypes,
    StringAttr opBundleSizesAttrName) {
  unsigned opBundleIndex = 0;
  for (const auto &[operands, types] :
       llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
    if (operands.size() != types.size())
      return parser.emitError(loc, "expected ")
             << operands.size()
             << " types for operand bundle operands for operand bundle #"
             << opBundleIndex << ", but actually got " << types.size();
    if (parser.resolveOperands(operands, types, loc, state.operands))
      return failure();
  }

  SmallVector<int32_t> opBundleSizes;
  opBundleSizes.reserve(opBundleOperands.size());
  for (const auto &operands : opBundleOperands)
    opBundleSizes.push_back(operands.size());

  state.addAttribute(
      opBundleSizesAttrName,
      DenseI32ArrayAttr::get(parser.getContext(), opBundleSizes));

  return success();
}

// <operation> ::= `llvm.call` (cconv)? (tailcallkind)? (function-id | ssa-use)
//                             `(` ssa-use-list `)`
//                             ( `vararg(` var-callee-type `)` )?
//                             ( `[` op-bundles-list `]` )?
//                             attribute-dict? `:` (type `,`)? function-type
ParseResult CallOp::parse(OpAsmParser &parser, OperationState &result) {
  SymbolRefAttr funcAttr;
  TypeAttr varCalleeType;
  SmallVector<OpAsmParser::UnresolvedOperand> operands;
  SmallVector<SmallVector<OpAsmParser::UnresolvedOperand>> opBundleOperands;
  SmallVector<SmallVector<Type>> opBundleOperandTypes;
  ArrayAttr opBundleTags;

  // Default to C Calling Convention if no keyword is provided.
  result.addAttribute(
      getCConvAttrName(result.name),
      CConvAttr::get(parser.getContext(),
                     parseOptionalLLVMKeyword<CConv>(parser, LLVM::CConv::C)));

  result.addAttribute(
      getTailCallKindAttrName(result.name),
      TailCallKindAttr::get(parser.getContext(),
                            parseOptionalLLVMKeyword<TailCallKind>(
                                parser, LLVM::TailCallKind::None)));

  // Parse a function pointer for indirect calls.
  if (parseOptionalCallFuncPtr(parser, operands))
    return failure();
  bool isDirect = operands.empty();

  // Parse a function identifier for direct calls.
  if (isDirect)
    if (parser.parseAttribute(funcAttr, "callee", result.attributes))
      return failure();

  // Parse the function arguments.
  if (parser.parseOperandList(operands, OpAsmParser::Delimiter::Paren))
    return failure();

  bool isVarArg = parser.parseOptionalKeyword("vararg").succeeded();
  if (isVarArg) {
    StringAttr varCalleeTypeAttrName =
        CallOp::getVarCalleeTypeAttrName(result.name);
    if (parser.parseLParen().failed() ||
        parser
            .parseAttribute(varCalleeType, varCalleeTypeAttrName,
                            result.attributes)
            .failed() ||
        parser.parseRParen().failed())
      return failure();
  }

  SMLoc opBundlesLoc = parser.getCurrentLocation();
  if (std::optional<ParseResult> result = parseOpBundles(
          parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
      result && failed(*result))
    return failure();
  if (opBundleTags && !opBundleTags.empty())
    result.addAttribute(CallOp::getOpBundleTagsAttrName(result.name).getValue(),
                        opBundleTags);

  if (parser.parseOptionalAttrDict(result.attributes))
    return failure();

  // Parse the trailing type list and resolve the operands.
  SmallVector<DictionaryAttr> argAttrs;
  SmallVector<DictionaryAttr> resultAttrs;
  if (parseCallTypeAndResolveOperands(parser, result, isDirect, operands,
                                      argAttrs, resultAttrs))
    return failure();
  call_interface_impl::addArgAndResultAttrs(
      parser.getBuilder(), result, argAttrs, resultAttrs,
      getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
  if (resolveOpBundleOperands(parser, opBundlesLoc, result, opBundleOperands,
                              opBundleOperandTypes,
                              getOpBundleSizesAttrName(result.name)))
    return failure();

  int32_t numOpBundleOperands = 0;
  for (const auto &operands : opBundleOperands)
    numOpBundleOperands += operands.size();

  result.addAttribute(
      CallOp::getOperandSegmentSizeAttr(),
      parser.getBuilder().getDenseI32ArrayAttr(
          {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
  return success();
}

LLVMFunctionType CallOp::getCalleeFunctionType() {
  if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
    return *varCalleeType;
  return getLLVMFuncType(getContext(), getResultTypes(), getArgOperands());
}

///===---------------------------------------------------------------------===//
/// LLVM::InvokeOp
///===---------------------------------------------------------------------===//

void InvokeOp::build(OpBuilder &builder, OperationState &state, LLVMFuncOp func,
                     ValueRange ops, Block *normal, ValueRange normalOps,
                     Block *unwind, ValueRange unwindOps) {
  auto calleeType = func.getFunctionType();
  build(builder, state, getCallOpResultTypes(calleeType),
        getCallOpVarCalleeType(calleeType), SymbolRefAttr::get(func), ops,
        /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, normalOps, unwindOps,
        nullptr, nullptr, /*default_func_attrs=*/nullptr, {}, {}, normal,
        unwind);
}

void InvokeOp::build(OpBuilder &builder, OperationState &state, TypeRange tys,
                     FlatSymbolRefAttr callee, ValueRange ops, Block *normal,
                     ValueRange normalOps, Block *unwind,
                     ValueRange unwindOps) {
  build(builder, state, tys,
        /*var_callee_type=*/nullptr, callee, ops, /*arg_attrs=*/nullptr,
        /*res_attrs=*/nullptr, normalOps, unwindOps, nullptr, nullptr,
        /*default_func_attrs=*/nullptr, {}, {}, normal, unwind);
}

void InvokeOp::build(OpBuilder &builder, OperationState &state,
                     LLVMFunctionType calleeType, FlatSymbolRefAttr callee,
                     ValueRange ops, Block *normal, ValueRange normalOps,
                     Block *unwind, ValueRange unwindOps) {
  build(builder, state, getCallOpResultTypes(calleeType),
        getCallOpVarCalleeType(calleeType), callee, ops,
        /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, normalOps, unwindOps,
        nullptr, nullptr, /*default_func_attrs=*/nullptr, {}, {}, normal,
        unwind);
}

SuccessorOperands InvokeOp::getSuccessorOperands(unsigned index) {
  assert(index < getNumSuccessors() && "invalid successor index");
  return SuccessorOperands(index == 0 ? getNormalDestOperandsMutable()
                                      : getUnwindDestOperandsMutable());
}

CallInterfaceCallable InvokeOp::getCallableForCallee() {
  // Direct call.
  if (FlatSymbolRefAttr calleeAttr = getCalleeAttr())
    return calleeAttr;
  // Indirect call, callee Value is the first operand.
  return getOperand(0);
}

void InvokeOp::setCalleeFromCallable(CallInterfaceCallable callee) {
  // Direct call.
  if (FlatSymbolRefAttr calleeAttr = getCalleeAttr()) {
    auto symRef = cast<SymbolRefAttr>(callee);
    return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
  }
  // Indirect call, callee Value is the first operand.
  return setOperand(0, cast<Value>(callee));
}

Operation::operand_range InvokeOp::getArgOperands() {
  return getArgOperandsImpl(*this);
}

MutableOperandRange InvokeOp::getArgOperandsMutable() {
  return MutableOperandRange(*this, getNumConsumedCalleeOperands(*this),
                             getArgOperandsImpl(*this).size());
}

LogicalResult InvokeOp::verify() {
  if (failed(verifyCallOpVarCalleeType(*this)))
    return failure();

  Block *unwindDest = getUnwindDest();
  if (unwindDest->empty())
    return emitError("must have at least one operation in unwind destination");

  // In unwind destination, first operation must be LandingpadOp
  if (!isa<LandingpadOp>(unwindDest->front()))
    return emitError("first operation in unwind destination should be a "
                     "llvm.landingpad operation");

  if (failed(verifyOperandBundles(*this)))
    return failure();

  return success();
}

void InvokeOp::print(OpAsmPrinter &p) {
  auto callee = getCallee();
  bool isDirect = callee.has_value();

  p << ' ';

  // Print calling convention.
  if (getCConv() != LLVM::CConv::C)
    p << stringifyCConv(getCConv()) << ' ';

  // Either function name or pointer
  if (isDirect)
    p.printSymbolName(callee.value());
  else
    p << getOperand(0);

  p << '(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) << ')';
  p << " to ";
  p.printSuccessorAndUseList(getNormalDest(), getNormalDestOperands());
  p << " unwind ";
  p.printSuccessorAndUseList(getUnwindDest(), getUnwindDestOperands());

  // Print the variadic callee type if the invoke is variadic.
  if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
    p << " vararg(" << *varCalleeType << ")";

  if (!getOpBundleOperands().empty()) {
    p << " ";
    printOpBundles(p, *this, getOpBundleOperands(),
                   getOpBundleOperands().getTypes(), getOpBundleTags());
  }

  p.printOptionalAttrDict((*this)->getAttrs(),
                          {getCalleeAttrName(), getOperandSegmentSizeAttr(),
                           getCConvAttrName(), getVarCalleeTypeAttrName(),
                           getOpBundleSizesAttrName(),
                           getOpBundleTagsAttrName(), getArgAttrsAttrName(),
                           getResAttrsAttrName()});

  p << " : ";
  if (!isDirect)
    p << getOperand(0).getType() << ", ";
  call_interface_impl::printFunctionSignature(
      p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
      getArgAttrsAttr(),
      /*isVariadic=*/false, getResultTypes(), getResAttrsAttr());
}

// <operation> ::= `llvm.invoke` (cconv)? (function-id | ssa-use)
//                  `(` ssa-use-list `)`
//                  `to` bb-id (`[` ssa-use-and-type-list `]`)?
//                  `unwind` bb-id (`[` ssa-use-and-type-list `]`)?
//                  ( `vararg(` var-callee-type `)` )?
//                  ( `[` op-bundles-list `]` )?
//                  attribute-dict? `:` (type `,`)?
//                  function-type-with-argument-attributes
ParseResult InvokeOp::parse(OpAsmParser &parser, OperationState &result) {
  SmallVector<OpAsmParser::UnresolvedOperand, 8> operands;
  SymbolRefAttr funcAttr;
  TypeAttr varCalleeType;
  SmallVector<SmallVector<OpAsmParser::UnresolvedOperand>> opBundleOperands;
  SmallVector<SmallVector<Type>> opBundleOperandTypes;
  ArrayAttr opBundleTags;
  Block *normalDest, *unwindDest;
  SmallVector<Value, 4> normalOperands, unwindOperands;
  Builder &builder = parser.getBuilder();

  // Default to C Calling Convention if no keyword is provided.
  result.addAttribute(
      getCConvAttrName(result.name),
      CConvAttr::get(parser.getContext(),
                     parseOptionalLLVMKeyword<CConv>(parser, LLVM::CConv::C)));

  // Parse a function pointer for indirect calls.
  if (parseOptionalCallFuncPtr(parser, operands))
    return failure();
  bool isDirect = operands.empty();

  // Parse a function identifier for direct calls.
  if (isDirect && parser.parseAttribute(funcAttr, "callee", result.attributes))
    return failure();

  // Parse the function arguments.
  if (parser.parseOperandList(operands, OpAsmParser::Delimiter::Paren) ||
      parser.parseKeyword("to") ||
      parser.parseSuccessorAndUseList(normalDest, normalOperands) ||
      parser.parseKeyword("unwind") ||
      parser.parseSuccessorAndUseList(unwindDest, unwindOperands))
    return failure();

  bool isVarArg = parser.parseOptionalKeyword("vararg").succeeded();
  if (isVarArg) {
    StringAttr varCalleeTypeAttrName =
        InvokeOp::getVarCalleeTypeAttrName(result.name);
    if (parser.parseLParen().failed() ||
        parser
            .parseAttribute(varCalleeType, varCalleeTypeAttrName,
                            result.attributes)
            .failed() ||
        parser.parseRParen().failed())
      return failure();
  }

  SMLoc opBundlesLoc = parser.getCurrentLocation();
  if (std::optional<ParseResult> result = parseOpBundles(
          parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
      result && failed(*result))
    return failure();
  if (opBundleTags && !opBundleTags.empty())
    result.addAttribute(
        InvokeOp::getOpBundleTagsAttrName(result.name).getValue(),
        opBundleTags);

  if (parser.parseOptionalAttrDict(result.attributes))
    return failure();

  // Parse the trailing type list and resolve the function operands.
  SmallVector<DictionaryAttr> argAttrs;
  SmallVector<DictionaryAttr> resultAttrs;
  if (parseCallTypeAndResolveOperands(parser, result, isDirect, operands,
                                      argAttrs, resultAttrs))
    return failure();
  call_interface_impl::addArgAndResultAttrs(
      parser.getBuilder(), result, argAttrs, resultAttrs,
      getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));

  if (resolveOpBundleOperands(parser, opBundlesLoc, result, opBundleOperands,
                              opBundleOperandTypes,
                              getOpBundleSizesAttrName(result.name)))
    return failure();

  result.addSuccessors({normalDest, unwindDest});
  result.addOperands(normalOperands);
  result.addOperands(unwindOperands);

  int32_t numOpBundleOperands = 0;
  for (const auto &operands : opBundleOperands)
    numOpBundleOperands += operands.size();

  result.addAttribute(
      InvokeOp::getOperandSegmentSizeAttr(),
      builder.getDenseI32ArrayAttr({static_cast<int32_t>(operands.size()),
                                    static_cast<int32_t>(normalOperands.size()),
                                    static_cast<int32_t>(unwindOperands.size()),
                                    numOpBundleOperands}));
  return success();
}

LLVMFunctionType InvokeOp::getCalleeFunctionType() {
  if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
    return *varCalleeType;
  return getLLVMFuncType(getContext(), getResultTypes(), getArgOperands());
}

///===----------------------------------------------------------------------===//
/// Verifying/Printing/Parsing for LLVM::LandingpadOp.
///===----------------------------------------------------------------------===//

LogicalResult LandingpadOp::verify() {
  Value value;
  if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
    if (!func.getPersonality())
      return emitError(
          "llvm.landingpad needs to be in a function with a personality");
  }

  // Consistency of llvm.landingpad result types is checked in
  // LLVMFuncOp::verify().

  if (!getCleanup() && getOperands().empty())
    return emitError("landingpad instruction expects at least one clause or "
                     "cleanup attribute");

  for (unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
    value = getOperand(idx);
    bool isFilter = llvm::isa<LLVMArrayType>(value.getType());
    if (isFilter) {
      // FIXME: Verify filter clauses when arrays are appropriately handled
    } else {
      // catch - global addresses only.
      // Bitcast ops should have global addresses as their args.
      if (auto bcOp = value.getDefiningOp<BitcastOp>()) {
        if (auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
          continue;
        return emitError("constant clauses expected").attachNote(bcOp.getLoc())
               << "global addresses expected as operand to "
                  "bitcast used in clauses for landingpad";
      }
      // ZeroOp and AddressOfOp allowed
      if (value.getDefiningOp<ZeroOp>())
        continue;
      if (value.getDefiningOp<AddressOfOp>())
        continue;
      return emitError("clause #")
             << idx << " is not a known constant - null, addressof, bitcast";
    }
  }
  return success();
}

void LandingpadOp::print(OpAsmPrinter &p) {
  p << (getCleanup() ? " cleanup " : " ");

  // Clauses
  for (auto value : getOperands()) {
    // Similar to llvm - if clause is an array type then it is filter
    // clause else catch clause
    bool isArrayTy = llvm::isa<LLVMArrayType>(value.getType());
    p << '(' << (isArrayTy ? "filter " : "catch ") << value << " : "
      << value.getType() << ") ";
  }

  p.printOptionalAttrDict((*this)->getAttrs(), {"cleanup"});

  p << ": " << getType();
}

// <operation> ::= `llvm.landingpad` `cleanup`?
//                 ((`catch` | `filter`) operand-type ssa-use)* attribute-dict?
ParseResult LandingpadOp::parse(OpAsmParser &parser, OperationState &result) {
  // Check for cleanup
  if (succeeded(parser.parseOptionalKeyword("cleanup")))
    result.addAttribute("cleanup", parser.getBuilder().getUnitAttr());

  // Parse clauses with types
  while (succeeded(parser.parseOptionalLParen()) &&
         (succeeded(parser.parseOptionalKeyword("filter")) ||
          succeeded(parser.parseOptionalKeyword("catch")))) {
    OpAsmParser::UnresolvedOperand operand;
    Type ty;
    if (parser.parseOperand(operand) || parser.parseColon() ||
        parser.parseType(ty) ||
        parser.resolveOperand(operand, ty, result.operands) ||
        parser.parseRParen())
      return failure();
  }

  Type type;
  if (parser.parseColon() || parser.parseType(type))
    return failure();

  result.addTypes(type);
  return success();
}

//===----------------------------------------------------------------------===//
// ExtractValueOp
//===----------------------------------------------------------------------===//

/// Extract the type at `position` in the LLVM IR aggregate type
/// `containerType`. Each element of `position` is an index into a nested
/// aggregate type. Return the resulting type or emit an error.
static Type getInsertExtractValueElementType(
    function_ref<InFlightDiagnostic(StringRef)> emitError, Type containerType,
    ArrayRef<int64_t> position) {
  Type llvmType = containerType;
  if (!isCompatibleType(containerType)) {
    emitError("expected LLVM IR Dialect type, got ") << containerType;
    return {};
  }

  // Infer the element type from the structure type: iteratively step inside the
  // type by taking the element type, indexed by the position attribute for
  // structures.  Check the position index before accessing, it is supposed to
  // be in bounds.
  for (int64_t idx : position) {
    if (auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
      if (idx < 0 || static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
        emitError("position out of bounds: ") << idx;
        return {};
      }
      llvmType = arrayType.getElementType();
    } else if (auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
      if (idx < 0 ||
          static_cast<unsigned>(idx) >= structType.getBody().size()) {
        emitError("position out of bounds: ") << idx;
        return {};
      }
      llvmType = structType.getBody()[idx];
    } else {
      emitError("expected LLVM IR structure/array type, got: ") << llvmType;
      return {};
    }
  }
  return llvmType;
}

/// Extract the type at `position` in the wrapped LLVM IR aggregate type
/// `containerType`.
static Type getInsertExtractValueElementType(Type llvmType,
                                             ArrayRef<int64_t> position) {
  for (int64_t idx : position) {
    if (auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
      llvmType = structType.getBody()[idx];
    else
      llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
  }
  return llvmType;
}

/// Extracts the element at the given index from an attribute. For
/// `ElementsAttr`, returns the element at the specified index, or `nullptr` if
/// the shaped type does not have rank 1. For `ArrayAttr`, returns the element
/// at the specified index. For `ZeroAttr`, `UndefAttr`, and `PoisonAttr`,
/// returns the attribute itself unchanged. Returns `nullptr` if the attribute
/// is not one of these types or if the index is out of bounds.
static Attribute extractElementAt(Attribute attr, size_t index) {
  if (auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
    ShapedType shapedType = elementsAttr.getShapedType();
    if (!shapedType.hasRank() || shapedType.getRank() != 1)
      return nullptr;
    if (index < static_cast<size_t>(elementsAttr.getNumElements()))
      return elementsAttr.getValues<Attribute>()[index];
    return nullptr;
  }
  if (auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
    if (index < arrayAttr.getValue().size())
      return arrayAttr[index];
    return nullptr;
  }
  if (isa<ZeroAttr, UndefAttr, PoisonAttr>(attr))
    return attr;
  return nullptr;
}

OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
  if (auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
    SmallVector<int64_t, 4> newPos(extractValueOp.getPosition());
    newPos.append(getPosition().begin(), getPosition().end());
    setPosition(newPos);
    getContainerMutable().set(extractValueOp.getContainer());
    return getResult();
  }

  Attribute containerAttr;
  if (matchPattern(getContainer(), m_Constant(&containerAttr))) {
    for (int64_t pos : getPosition()) {
      containerAttr = extractElementAt(containerAttr, pos);
      if (!containerAttr)
        return nullptr;
    }
    return containerAttr;
  }

  Value container = getContainer();
  ArrayRef<int64_t> extractPos = getPosition();
  while (auto insertValueOp = container.getDefiningOp<InsertValueOp>()) {
    ArrayRef<int64_t> insertPos = insertValueOp.getPosition();
    auto extractPosSize = extractPos.size();
    auto insertPosSize = insertPos.size();

    // Case 1: Exact match of positions.
    if (extractPos == insertPos)
      return insertValueOp.getValue();

    // Case 2: Insert position is a prefix of extract position. Continue
    // traversal with the inserted value. Example:
    // ```
    // %0 = llvm.insertvalue %arg1, %undef[0] : !llvm.struct<(i32, i32, i32)>
    // %1 = llvm.insertvalue %arg2, %0[1] : !llvm.struct<(i32, i32, i32)>
    // %2 = llvm.insertvalue %arg3, %1[2] : !llvm.struct<(i32, i32, i32)>
    // %3 = llvm.insertvalue %2, %foo[0]
    //     : !llvm.struct<(struct<(i32, i32, i32)>, i64)>
    // %4 = llvm.extractvalue %3[0, 0]
    //     : !llvm.struct<(struct<(i32, i32, i32)>, i64)>
    // ```
    // In the above example, %4 is folded to %arg1.
    if (extractPosSize > insertPosSize &&
        extractPos.take_front(insertPosSize) == insertPos) {
      container = insertValueOp.getValue();
      extractPos = extractPos.drop_front(insertPosSize);
      continue;
    }

    // Case 3: Try to continue the traversal with the container value.

    // If extract position is a prefix of insert position, stop propagating back
    // as it will miss dependencies. For instance, %3 should not fold to %f0 in
    // the following example:
    // ```
    //   %1 = llvm.insertvalue %f0, %0[0, 0] :
    //     !llvm.array<4 x !llvm.array<4 x f32>>
    //   %2 = llvm.insertvalue %arr, %1[0] :
    //     !llvm.array<4 x !llvm.array<4 x f32>>
    //   %3 = llvm.extractvalue %2[0, 0] : !llvm.array<4 x !llvm.array<4 x f32>>
    // ```
    if (insertPosSize > extractPosSize &&
        extractPos == insertPos.take_front(extractPosSize))
      break;
    // If neither a prefix, nor the exact position, we can extract out of the
    // value being inserted into. Moreover, we can try again if that operand
    // is itself an insertvalue expression.
    container = insertValueOp.getContainer();
  }

  // We failed to resolve past this container either because it is not an
  // InsertValueOp, or it is an InsertValueOp that partially overlaps with the
  // value being extracted. Update to read from this container instead.
  if (container == getContainer())
    return {};
  setPosition(extractPos);
  getContainerMutable().assign(container);
  return getResult();
}

LogicalResult ExtractValueOp::verify() {
  auto emitError = [this](StringRef msg) { return emitOpError(msg); };
  Type valueType = getInsertExtractValueElementType(
      emitError, getContainer().getType(), getPosition());
  if (!valueType)
    return failure();

  if (getRes().getType() != valueType)
    return emitOpError() << "Type mismatch: extracting from "
                         << getContainer().getType() << " should produce "
                         << valueType << " but this op returns "
                         << getRes().getType();
  return success();
}

void ExtractValueOp::build(OpBuilder &builder, OperationState &state,
                           Value container, ArrayRef<int64_t> position) {
  build(builder, state,
        getInsertExtractValueElementType(container.getType(), position),
        container, builder.getAttr<DenseI64ArrayAttr>(position));
}

//===----------------------------------------------------------------------===//
// InsertValueOp
//===----------------------------------------------------------------------===//

namespace {
/// Update any ExtractValueOps using a given InsertValueOp to instead read from
/// the closest InsertValueOp in the chain leading up to the current op that
/// writes to the same member. This traversal could be done entirely in
/// ExtractValueOp::fold, but doing it here significantly speeds things up
/// because we can handle several ExtractValueOps with a single traversal.
/// For instance, in this example:
///   %i0 = llvm.insertvalue %v0, %undef[0]
///   %i1 = llvm.insertvalue %v1, %0[1]
///   ...
///   %i999 = llvm.insertvalue %v999, %998[999]
///   %e0 = llvm.extractvalue %i999[0]
///   %e1 = llvm.extractvalue %i999[1]
///   ...
///   %e999 = llvm.extractvalue %i999[999]
/// Individually running the folder on each extractvalue would require
/// traversing the insertvalue chain 1000 times, but running this pattern on the
/// InsertValueOp would allow us to achieve the same result with a single
/// traversal. The resulting IR after this pattern will then be:
///   %i0 = llvm.insertvalue %v0, %undef[0]
///   %i1 = llvm.insertvalue %v1, %0[1]
///   ...
///   %i999 = llvm.insertvalue %v999, %998[999]
///   %e0 = llvm.extractvalue %i0[0]
///   %e1 = llvm.extractvalue %i1[1]
///   ...
///   %e999 = llvm.extractvalue %i999[999]
struct ResolveExtractValueSource : public OpRewritePattern<InsertValueOp> {
  using OpRewritePattern::OpRewritePattern;

  LogicalResult matchAndRewrite(InsertValueOp insertOp,
                                PatternRewriter &rewriter) const override {
    bool changed = false;
    // Map each position in the top-level struct to the ExtractOps that read
    // from it. For the example in the doc-comment above this map will be empty
    // when we visit ops %i0 - %i998. For %i999, it will contain:
    //   0 -> { %e0 }, 1 -> { %e1 }, ... 999-> { %e999 }
    DenseMap<int64_t, SmallVector<ExtractValueOp, 4>> posToExtractOps;
    auto insertBaseIdx = insertOp.getPosition()[0];
    for (auto &use : insertOp->getUses()) {
      if (auto extractOp = dyn_cast<ExtractValueOp>(use.getOwner())) {
        auto baseIdx = extractOp.getPosition()[0];
        // We can skip reads of the member that insertOp writes to since they
        // will not be updated.
        if (baseIdx == insertBaseIdx)
          continue;
        posToExtractOps[baseIdx].push_back(extractOp);
      }
    }
    // Walk up the chain of insertions and try to resolve the remaining
    // extractions that access the same member.
    Value nextContainer = insertOp.getContainer();
    while (!posToExtractOps.empty()) {
      auto curInsert =
          dyn_cast_or_null<InsertValueOp>(nextContainer.getDefiningOp());
      if (!curInsert)
        break;
      nextContainer = curInsert.getContainer();

      // Check if any extractions read the member written by this insertion.
      auto curInsertBaseIdx = curInsert.getPosition()[0];
      auto it = posToExtractOps.find(curInsertBaseIdx);
      if (it == posToExtractOps.end())
        continue;

      // Update the ExtractOps to read from the current insertion.
      for (auto &extractOp : it->second) {
        rewriter.modifyOpInPlace(extractOp, [&] {
          extractOp.getContainerMutable().assign(curInsert);
        });
      }
      // The entry should never be empty if it exists, so if we are at this
      // point, set changed to true.
      assert(!it->second.empty());
      changed |= true;
      posToExtractOps.erase(it);
    }
    // There was no insertion along the chain that wrote the member accessed by
    // these extracts. So we can update them to use the top of the chain.
    for (auto &[baseIdx, extracts] : posToExtractOps) {
      for (auto &extractOp : extracts) {
        rewriter.modifyOpInPlace(extractOp, [&] {
          extractOp.getContainerMutable().assign(nextContainer);
        });
      }
      assert(!extracts.empty() && "Empty list in map");
      changed = true;
    }
    return success(changed);
  }
};
} // namespace

void InsertValueOp::getCanonicalizationPatterns(RewritePatternSet &patterns,
                                                MLIRContext *context) {
  patterns.add<ResolveExtractValueSource>(context);
}

/// Infer the value type from the container type and position.
static ParseResult
parseInsertExtractValueElementType(AsmParser &parser, Type &valueType,
                                   Type containerType,
                                   DenseI64ArrayAttr position) {
  valueType = getInsertExtractValueElementType(
      [&](StringRef msg) {
        return parser.emitError(parser.getCurrentLocation(), msg);
      },
      containerType, position.asArrayRef());
  return success(!!valueType);
}

/// Nothing to print for an inferred type.
static void printInsertExtractValueElementType(AsmPrinter &printer,
                                               Operation *op, Type valueType,
                                               Type containerType,
                                               DenseI64ArrayAttr position) {}

LogicalResult InsertValueOp::verify() {
  auto emitError = [this](StringRef msg) { return emitOpError(msg); };
  Type valueType = getInsertExtractValueElementType(
      emitError, getContainer().getType(), getPosition());
  if (!valueType)
    return failure();

  if (getValue().getType() != valueType)
    return emitOpError() << "Type mismatch: cannot insert "
                         << getValue().getType() << " into "
                         << getContainer().getType();

  return success();
}

//===----------------------------------------------------------------------===//
// ReturnOp
//===----------------------------------------------------------------------===//

LogicalResult ReturnOp::verify() {
  auto parent = (*this)->getParentOfType<LLVMFuncOp>();
  if (!parent)
    return success();

  Type expectedType = parent.getFunctionType().getReturnType();
  if (llvm::isa<LLVMVoidType>(expectedType)) {
    if (!getArg())
      return success();
    InFlightDiagnostic diag = emitOpError("expected no operands");
    diag.attachNote(parent->getLoc()) << "when returning from function";
    return diag;
  }
  if (!getArg()) {
    if (llvm::isa<LLVMVoidType>(expectedType))
      return success();
    InFlightDiagnostic diag = emitOpError("expected 1 operand");
    diag.attachNote(parent->getLoc()) << "when returning from function";
    return diag;
  }
  if (expectedType != getArg().getType()) {
    InFlightDiagnostic diag = emitOpError("mismatching result types");
    diag.attachNote(parent->getLoc()) << "when returning from function";
    return diag;
  }
  return success();
}

//===----------------------------------------------------------------------===//
// LLVM::AddressOfOp.
//===----------------------------------------------------------------------===//

GlobalOp AddressOfOp::getGlobal(SymbolTableCollection &symbolTable) {
  return dyn_cast_or_null<GlobalOp>(
      symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr()));
}

LLVMFuncOp AddressOfOp::getFunction(SymbolTableCollection &symbolTable) {
  return dyn_cast_or_null<LLVMFuncOp>(
      symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr()));
}

AliasOp AddressOfOp::getAlias(SymbolTableCollection &symbolTable) {
  return dyn_cast_or_null<AliasOp>(
      symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr()));
}

IFuncOp AddressOfOp::getIFunc(SymbolTableCollection &symbolTable) {
  return dyn_cast_or_null<IFuncOp>(
      symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr()));
}

LogicalResult
AddressOfOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
  Operation *symbol =
      symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr());

  auto global = dyn_cast_or_null<GlobalOp>(symbol);
  auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
  auto alias = dyn_cast_or_null<AliasOp>(symbol);
  auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);

  if (!global && !function && !alias && !ifunc)
    return emitOpError("must reference a global defined by 'llvm.mlir.global', "
                       "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");

  LLVMPointerType type = getType();
  if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
      (alias && alias.getAddrSpace() != type.getAddressSpace()))
    return emitOpError("pointer address space must match address space of the "
                       "referenced global or alias");

  return success();
}

// AddressOfOp constant-folds to the global symbol name.
OpFoldResult LLVM::AddressOfOp::fold(FoldAdaptor) {
  return getGlobalNameAttr();
}

//===----------------------------------------------------------------------===//
// LLVM::DSOLocalEquivalentOp
//===----------------------------------------------------------------------===//

LLVMFuncOp
DSOLocalEquivalentOp::getFunction(SymbolTableCollection &symbolTable) {
  return dyn_cast_or_null<LLVMFuncOp>(symbolTable.lookupSymbolIn(
      parentLLVMModule(*this), getFunctionNameAttr()));
}

AliasOp DSOLocalEquivalentOp::getAlias(SymbolTableCollection &symbolTable) {
  return dyn_cast_or_null<AliasOp>(symbolTable.lookupSymbolIn(
      parentLLVMModule(*this), getFunctionNameAttr()));
}

LogicalResult
DSOLocalEquivalentOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
  Operation *symbol = symbolTable.lookupSymbolIn(parentLLVMModule(*this),
                                                 getFunctionNameAttr());
  auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
  auto alias = dyn_cast_or_null<AliasOp>(symbol);

  if (!function && !alias)
    return emitOpError(
        "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");

  if (alias) {
    if (alias.getInitializer()
            .walk([&](AddressOfOp addrOp) {
              if (addrOp.getGlobal(symbolTable))
                return WalkResult::interrupt();
              return WalkResult::advance();
            })
            .wasInterrupted())
      return emitOpError("must reference an alias to a function");
  }

  if ((function && function.getLinkage() == LLVM::Linkage::ExternWeak) ||
      (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
    return emitOpError(
        "target function with 'extern_weak' linkage not allowed");

  return success();
}

/// Fold a dso_local_equivalent operation to a dedicated dso_local_equivalent
/// attribute.
OpFoldResult DSOLocalEquivalentOp::fold(FoldAdaptor) {
  return DSOLocalEquivalentAttr::get(getContext(), getFunctionNameAttr());
}

//===----------------------------------------------------------------------===//
// Verifier for LLVM::ComdatOp.
//===----------------------------------------------------------------------===//

void ComdatOp::build(OpBuilder &builder, OperationState &result,
                     StringRef symName) {
  result.addAttribute(getSymNameAttrName(result.name),
                      builder.getStringAttr(symName));
  Region *body = result.addRegion();
  body->emplaceBlock();
}

LogicalResult ComdatOp::verifyRegions() {
  Region &body = getBody();
  for (Operation &op : body.getOps())
    if (!isa<ComdatSelectorOp>(op))
      return op.emitError(
          "only comdat selector symbols can appear in a comdat region");

  return success();
}

//===----------------------------------------------------------------------===//
// Builder, printer and verifier for LLVM::GlobalOp.
//===----------------------------------------------------------------------===//

void GlobalOp::build(OpBuilder &builder, OperationState &result, Type type,
                     bool isConstant, Linkage linkage, StringRef name,
                     Attribute value, uint64_t alignment, unsigned addrSpace,
                     bool dsoLocal, ThreadLocalMode threadModel,
                     SymbolRefAttr comdat, ArrayRef<NamedAttribute> attrs,
                     ArrayRef<Attribute> dbgExprs) {
  result.addAttribute(getSymNameAttrName(result.name),
                      builder.getStringAttr(name));
  result.addAttribute(getGlobalTypeAttrName(result.name), TypeAttr::get(type));
  result.addAttribute(
      getTlsModeAttrName(result.name),
      ThreadLocalModeAttr::get(builder.getContext(), threadModel));
  if (isConstant)
    result.addAttribute(getConstantAttrName(result.name),
                        builder.getUnitAttr());
  if (value)
    result.addAttribute(getValueAttrName(result.name), value);
  if (dsoLocal)
    result.addAttribute(getDsoLocalAttrName(result.name),
                        builder.getUnitAttr());
  if (comdat)
    result.addAttribute(getComdatAttrName(result.name), comdat);

  // Only add an alignment attribute if the "alignment" input
  // is different from 0. The value must also be a power of two, but
  // this is tested in GlobalOp::verify, not here.
  if (alignment != 0)
    result.addAttribute(getAlignmentAttrName(result.name),
                        builder.getI64IntegerAttr(alignment));

  result.addAttribute(getLinkageAttrName(result.name),
                      LinkageAttr::get(builder.getContext(), linkage));
  if (addrSpace != 0)
    result.addAttribute(getAddrSpaceAttrName(result.name),
                        builder.getI32IntegerAttr(addrSpace));
  result.attributes.append(attrs.begin(), attrs.end());

  if (!dbgExprs.empty())
    result.addAttribute(getDbgExprsAttrName(result.name),
                        ArrayAttr::get(builder.getContext(), dbgExprs));

  result.addRegion();
}

template <typename OpType>
static void printCommonGlobalAndAlias(OpAsmPrinter &p, OpType op) {
  p << ' ' << stringifyLinkage(op.getLinkage()) << ' ';
  StringRef visibility = stringifyVisibility(op.getVisibility_());
  if (!visibility.empty())
    p << visibility << ' ';

  if (ThreadLocalMode mode = op.getTlsMode();
      mode != ThreadLocalMode::NotThreadLocal) {
    p << "thread_local";
    if (mode != ThreadLocalMode::GeneralDynamic)
      p << '(' << mode << ')';
    p << ' ';
  }

  if (auto unnamedAddr = op.getUnnamedAddr()) {
    StringRef str = stringifyUnnamedAddr(*unnamedAddr);
    if (!str.empty())
      p << str << ' ';
  }
}

void GlobalOp::print(OpAsmPrinter &p) {
  printCommonGlobalAndAlias<GlobalOp>(p, *this);
  if (getConstant())
    p << "constant ";
  p.printSymbolName(getSymName());
  p << '(';
  if (auto value = getValueOrNull())
    p.printAttribute(value);
  p << ')';
  if (auto comdat = getComdat())
    p << " comdat(" << *comdat << ')';

  // Note that the alignment attribute is printed using the
  // default syntax here, even though it is an inherent attribute
  // (as defined in https://mlir.llvm.org/docs/LangRef/#attributes)
  p.printOptionalAttrDict((*this)->getAttrs(),
                          {SymbolTable::getSymbolAttrName(),
                           getGlobalTypeAttrName(), getConstantAttrName(),
                           getValueAttrName(), getLinkageAttrName(),
                           getUnnamedAddrAttrName(), getTlsModeAttrName(),
                           getVisibility_AttrName(), getComdatAttrName()});

  // Print the trailing type unless it's a string global.
  if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
    return;
  p << " : " << getType();

  Region &initializer = getInitializerRegion();
  if (!initializer.empty()) {
    p << ' ';
    p.printRegion(initializer, /*printEntryBlockArgs=*/false);
  }
}

static LogicalResult verifyComdat(Operation *op,
                                  std::optional<SymbolRefAttr> attr) {
  if (!attr)
    return success();

  auto *comdatSelector = SymbolTable::lookupNearestSymbolFrom(op, *attr);
  if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
    return op->emitError() << "expected comdat symbol";

  return success();
}

static LogicalResult verifyBlockTags(LLVMFuncOp funcOp) {
  llvm::DenseSet<BlockTagAttr> blockTags;
  // Note that presence of `BlockTagOp`s currently can't prevent an unrecheable
  // block to be removed by canonicalizer's region simplify pass, which needs to
  // be dialect aware to allow extra constraints to be described.
  WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
    if (blockTags.contains(blockTagOp.getTag())) {
      blockTagOp.emitError()
          << "duplicate block tag '" << blockTagOp.getTag().getId()
          << "' in the same function: ";
      return WalkResult::interrupt();
    }
    blockTags.insert(blockTagOp.getTag());
    return WalkResult::advance();
  });

  return failure(res.wasInterrupted());
}

/// Parse common attributes that might show up in the same order in both
/// GlobalOp and AliasOp.
template <typename OpType>
static ParseResult parseCommonGlobalAndAlias(OpAsmParser &parser,
                                             OperationState &result) {
  MLIRContext *ctx = parser.getContext();
  // Parse optional linkage, default to External.
  result.addAttribute(
      OpType::getLinkageAttrName(result.name),
      LLVM::LinkageAttr::get(ctx, parseOptionalLLVMKeyword<Linkage>(
                                      parser, LLVM::Linkage::External)));

  // Parse optional visibility, default to Default.
  result.addAttribute(OpType::getVisibility_AttrName(result.name),
                      parser.getBuilder().getI64IntegerAttr(
                          parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
                              parser, LLVM::Visibility::Default)));

  if (succeeded(parser.parseOptionalKeyword("thread_local"))) {
    ThreadLocalMode threadModel = ThreadLocalMode::GeneralDynamic;

    if (succeeded(parser.parseOptionalLParen())) {
      SMLoc kwLoc;
      if (parser.getCurrentLocation(&kwLoc))
        return failure();
      threadModel = parseOptionalLLVMKeyword<ThreadLocalMode>(
          parser, ThreadLocalMode::NotThreadLocal);
      if (threadModel == ThreadLocalMode::NotThreadLocal) {
        parser.emitError(kwLoc, "invalid value for thread_local");
        return failure();
      }
      if (parser.parseRParen())
        return failure();
    }
    result.addAttribute(OpType::getTlsModeAttrName(result.name),
                        ThreadLocalModeAttr::get(ctx, threadModel));
  }

  // Parse optional UnnamedAddr, default to None.
  result.addAttribute(OpType::getUnnamedAddrAttrName(result.name),
                      parser.getBuilder().getI64IntegerAttr(
                          parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
                              parser, LLVM::UnnamedAddr::None)));

  return success();
}

// operation ::= `llvm.mlir.global` linkage? visibility?
//               (`unnamed_addr` | `local_unnamed_addr`)?
//               (`thread_local` (`(` tls-mode `)`)? )?
//               `constant`? `@` identifier
//               `(` attribute? `)` (`comdat(` symbol-ref-id `)`)?
//               attribute-list? (`:` type)? region?
//
// The type can be omitted for string attributes, in which case it will be
// inferred from the value of the string as [strlen(value) x i8].
ParseResult GlobalOp::parse(OpAsmParser &parser, OperationState &result) {
  // Call into common parsing between GlobalOp and AliasOp.
  if (parseCommonGlobalAndAlias<GlobalOp>(parser, result).failed())
    return failure();

  if (succeeded(parser.parseOptionalKeyword("constant")))
    result.addAttribute(getConstantAttrName(result.name),
                        parser.getBuilder().getUnitAttr());

  StringAttr name;
  if (parser.parseSymbolName(name, getSymNameAttrName(result.name),
                             result.attributes) ||
      parser.parseLParen())
    return failure();

  Attribute value;
  if (parser.parseOptionalRParen()) {
    if (parser.parseAttribute(value, getValueAttrName(result.name),
                              result.attributes) ||
        parser.parseRParen())
      return failure();
  }

  if (succeeded(parser.parseOptionalKeyword("comdat"))) {
    SymbolRefAttr comdat;
    if (parser.parseLParen() || parser.parseAttribute(comdat) ||
        parser.parseRParen())
      return failure();

    result.addAttribute(getComdatAttrName(result.name), comdat);
  }

  SmallVector<Type, 1> types;
  if (parser.parseOptionalAttrDict(result.attributes) ||
      parser.parseOptionalColonTypeList(types))
    return failure();

  if (types.size() > 1)
    return parser.emitError(parser.getNameLoc(), "expected zero or one type");

  Region &initRegion = *result.addRegion();
  if (types.empty()) {
    if (auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
      MLIRContext *context = parser.getContext();
      auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
                                                strAttr.getValue().size());
      types.push_back(arrayType);
    } else {
      return parser.emitError(parser.getNameLoc(),
                              "type can only be omitted for string globals");
    }
  } else {
    OptionalParseResult parseResult =
        parser.parseOptionalRegion(initRegion, /*arguments=*/{},
                                   /*argTypes=*/{});
    if (parseResult.has_value() && failed(*parseResult))
      return failure();
  }

  result.addAttribute(getGlobalTypeAttrName(result.name),
                      TypeAttr::get(types[0]));
  return success();
}

static bool isZeroAttribute(Attribute value) {
  if (auto intValue = llvm::dyn_cast<IntegerAttr>(value))
    return intValue.getValue().isZero();
  if (auto fpValue = llvm::dyn_cast<FloatAttr>(value))
    return fpValue.getValue().isZero();
  if (auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
    return isZeroAttribute(splatValue.getSplatValue<Attribute>());
  if (auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
    return llvm::all_of(elementsValue.getValues<Attribute>(), isZeroAttribute);
  if (auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
    return llvm::all_of(arrayValue.getValue(), isZeroAttribute);
  return false;
}

LogicalResult GlobalOp::verify() {
  bool validType = isCompatibleOuterType(getType())
                       ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
                                    LLVMLabelType>(getType())
                       : llvm::isa<PointerElementTypeInterface>(getType());
  if (!validType)
    return emitOpError(
        "expects type to be a valid element type for an LLVM global");
  if ((*this)->getParentOp() && !satisfiesLLVMModule((*this)->getParentOp()))
    return emitOpError("must appear at the module level");

  if (auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
    auto type = llvm::dyn_cast<LLVMArrayType>(getType());
    IntegerType elementType =
        type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
    if (!elementType || elementType.getWidth() != 8 ||
        type.getNumElements() != strAttr.getValue().size())
      return emitOpError(
          "requires an i8 array type of the length equal to that of the string "
          "attribute");
  }

  if (auto targetExtType = dyn_cast<LLVMTargetExtType>(getType())) {
    if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
      return emitOpError()
             << "this target extension type cannot be used in a global";

    if (Attribute value = getValueOrNull())
      return emitOpError() << "global with target extension type can only be "
                              "initialized with zero-initializer";
  }

  if (getLinkage() == Linkage::Common) {
    if (Attribute value = getValueOrNull()) {
      if (!isZeroAttribute(value)) {
        return emitOpError()
               << "expected zero value for '"
               << stringifyLinkage(Linkage::Common) << "' linkage";
      }
    }
  }

  if (getLinkage() == Linkage::Appending) {
    if (!llvm::isa<LLVMArrayType>(getType())) {
      return emitOpError() << "expected array type for '"
                           << stringifyLinkage(Linkage::Appending)
                           << "' linkage";
    }
  }

  if (failed(verifyComdat(*this, getComdat())))
    return failure();

  std::optional<uint64_t> alignAttr = getAlignment();
  if (alignAttr.has_value()) {
    uint64_t value = alignAttr.value();
    if (!llvm::isPowerOf2_64(value))
      return emitError() << "alignment attribute is not a power of 2";
  }

  return success();
}

LogicalResult GlobalOp::verifyRegions() {
  if (Block *b = getInitializerBlock()) {
    ReturnOp ret = cast<ReturnOp>(b->getTerminator());
    if (ret.operand_type_begin() == ret.operand_type_end())
      return emitOpError("initializer region cannot return void");
    if (*ret.operand_type_begin() != getType())
      return emitOpError("initializer region type ")
             << *ret.operand_type_begin() << " does not match global type "
             << getType();

    for (Operation &op : *b) {
      auto iface = dyn_cast<MemoryEffectOpInterface>(op);
      if (!iface || !iface.hasNoEffect())
        return op.emitError()
               << "ops with side effects not allowed in global initializers";
    }

    if (getValueOrNull())
      return emitOpError("cannot have both initializer value and region");
  }

  return success();
}

//===----------------------------------------------------------------------===//
// LLVM::GlobalCtorsOp
//===----------------------------------------------------------------------===//

static LogicalResult checkGlobalXtorData(Operation *op, ArrayAttr data) {
  if (data.empty())
    return success();

  if (llvm::all_of(data.getAsRange<Attribute>(), [](Attribute v) {
        return isa<FlatSymbolRefAttr, ZeroAttr>(v);
      }))
    return success();
  return op->emitError("data element must be symbol or #llvm.zero");
}

LogicalResult
GlobalCtorsOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
  for (Attribute ctor : getCtors()) {
    if (failed(verifySymbolAttrUse(llvm::cast<FlatSymbolRefAttr>(ctor), *this,
                                   symbolTable)))
      return failure();
  }
  return success();
}

LogicalResult GlobalCtorsOp::verify() {
  if (checkGlobalXtorData(*this, getData()).failed())
    return failure();

  if (getCtors().size() == getPriorities().size() &&
      getCtors().size() == getData().size())
    return success();
  return emitError(
      "ctors, priorities, and data must have the same number of elements");
}

//===----------------------------------------------------------------------===//
// LLVM::GlobalDtorsOp
//===----------------------------------------------------------------------===//

LogicalResult
GlobalDtorsOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
  for (Attribute dtor : getDtors()) {
    if (failed(verifySymbolAttrUse(llvm::cast<FlatSymbolRefAttr>(dtor), *this,
                                   symbolTable)))
      return failure();
  }
  return success();
}

LogicalResult GlobalDtorsOp::verify() {
  if (checkGlobalXtorData(*this, getData()).failed())
    return failure();

  if (getDtors().size() == getPriorities().size() &&
      getDtors().size() == getData().size())
    return success();
  return emitError(
      "dtors, priorities, and data must have the same number of elements");
}

//===----------------------------------------------------------------------===//
// Builder, printer and verifier for LLVM::AliasOp.
//===----------------------------------------------------------------------===//

void AliasOp::build(OpBuilder &builder, OperationState &result, Type type,
                    Linkage linkage, StringRef name, bool dsoLocal,
                    ThreadLocalMode threadModel,
                    ArrayRef<NamedAttribute> attrs) {
  result.addAttribute(getSymNameAttrName(result.name),
                      builder.getStringAttr(name));
  result.addAttribute(getAliasTypeAttrName(result.name), TypeAttr::get(type));
  result.addAttribute(
      getTlsModeAttrName(result.name),
      ThreadLocalModeAttr::get(builder.getContext(), threadModel));
  if (dsoLocal)
    result.addAttribute(getDsoLocalAttrName(result.name),
                        builder.getUnitAttr());

  result.addAttribute(getLinkageAttrName(result.name),
                      LinkageAttr::get(builder.getContext(), linkage));
  result.attributes.append(attrs.begin(), attrs.end());

  result.addRegion();
}

void AliasOp::print(OpAsmPrinter &p) {
  printCommonGlobalAndAlias<AliasOp>(p, *this);

  p.printSymbolName(getSymName());
  p.printOptionalAttrDict((*this)->getAttrs(),
                          {SymbolTable::getSymbolAttrName(),
                           getAliasTypeAttrName(), getLinkageAttrName(),
                           getUnnamedAddrAttrName(), getTlsModeAttrName(),
                           getVisibility_AttrName()});

  // Print the trailing type.
  p << " : " << getType() << ' ';
  // Print the initializer region.
  p.printRegion(getInitializerRegion(), /*printEntryBlockArgs=*/false);
}

// operation ::= `llvm.mlir.alias` linkage? visibility?
//               (`unnamed_addr` | `local_unnamed_addr`)?
//               (`thread_local` (`(` tls-mode `)`)? )?
//               `@` identifier `(` attribute? `)`
//               attribute-list? `:` type region
//
ParseResult AliasOp::parse(OpAsmParser &parser, OperationState &result) {
  // Call into common parsing between GlobalOp and AliasOp.
  if (parseCommonGlobalAndAlias<AliasOp>(parser, result).failed())
    return failure();

  StringAttr name;
  if (parser.parseSymbolName(name, getSymNameAttrName(result.name),
                             result.attributes))
    return failure();

  SmallVector<Type, 1> types;
  if (parser.parseOptionalAttrDict(result.attributes) ||
      parser.parseOptionalColonTypeList(types))
    return failure();

  if (types.size() > 1)
    return parser.emitError(parser.getNameLoc(), "expected zero or one type");

  Region &initRegion = *result.addRegion();
  if (parser.parseRegion(initRegion).failed())
    return failure();

  result.addAttribute(getAliasTypeAttrName(result.name),
                      TypeAttr::get(types[0]));
  return success();
}

LogicalResult AliasOp::verify() {
  bool validType = isCompatibleOuterType(getType())
                       ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
                                    LLVMLabelType>(getType())
                       : llvm::isa<PointerElementTypeInterface>(getType());
  if (!validType)
    return emitOpError(
        "expects type to be a valid element type for an LLVM global alias");

  // This matches LLVM IR verification logic, see llvm/lib/IR/Verifier.cpp
  switch (getLinkage()) {
  case Linkage::External:
  case Linkage::Internal:
  case Linkage::Private:
  case Linkage::Weak:
  case Linkage::WeakODR:
  case Linkage::Linkonce:
  case Linkage::LinkonceODR:
  case Linkage::AvailableExternally:
    break;
  default:
    return emitOpError()
           << "'" << stringifyLinkage(getLinkage())
           << "' linkage not supported in aliases, available options: private, "
              "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
              "available_externally";
  }

  return success();
}

LogicalResult AliasOp::verifyRegions() {
  Block &b = getInitializerBlock();
  auto ret = cast<ReturnOp>(b.getTerminator());
  if (ret.getNumOperands() == 0 ||
      !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
    return emitOpError("initializer region must always return a pointer");

  for (Operation &op : b) {
    auto iface = dyn_cast<MemoryEffectOpInterface>(op);
    if (!iface || !iface.hasNoEffect())
      return op.emitError()
             << "ops with side effects are not allowed in alias initializers";
  }

  return success();
}

unsigned AliasOp::getAddrSpace() {
  Block &initializer = getInitializerBlock();
  auto ret = cast<ReturnOp>(initializer.getTerminator());
  auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
  return ptrTy.getAddressSpace();
}

//===----------------------------------------------------------------------===//
// IFuncOp
//===----------------------------------------------------------------------===//

void IFuncOp::build(OpBuilder &builder, OperationState &result, StringRef name,
                    Type iFuncType, StringRef resolverName, Type resolverType,
                    Linkage linkage, LLVM::Visibility visibility) {
  return build(builder, result, name, iFuncType, resolverName, resolverType,
               linkage, /*dso_local=*/false, /*address_space=*/0,
               UnnamedAddr::None, visibility);
}

LogicalResult IFuncOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
  Operation *symbol =
      symbolTable.lookupSymbolIn(parentLLVMModule(*this), getResolverAttr());
  // This matches LLVM IR verification logic, see llvm/lib/IR/Verifier.cpp
  auto resolver = dyn_cast<LLVMFuncOp>(symbol);
  auto alias = dyn_cast<AliasOp>(symbol);
  while (alias) {
    Block &initBlock = alias.getInitializerBlock();
    auto returnOp = cast<ReturnOp>(initBlock.getTerminator());
    auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
    // FIXME: This is a best effort solution. The AliasOp body might be more
    // complex and in that case we bail out with success. To completely match
    // the LLVM IR logic it would be necessary to implement proper alias and
    // cast stripping.
    if (!addrOp)
      return success();
    resolver = addrOp.getFunction(symbolTable);
    alias = addrOp.getAlias(symbolTable);
  }
  if (!resolver)
    return emitOpError("must have a function resolver");
  Linkage linkage = resolver.getLinkage();
  if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
    return emitOpError("resolver must be a definition");
  if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
    return emitOpError("resolver must return a pointer");
  auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
  if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
    return emitOpError("resolver has incorrect type");
  return success();
}

LogicalResult IFuncOp::verify() {
  switch (getLinkage()) {
  case Linkage::External:
  case Linkage::Internal:
  case Linkage::Private:
  case Linkage::Weak:
  case Linkage::WeakODR:
  case Linkage::Linkonce:
  case Linkage::LinkonceODR:
    break;
  default:
    return emitOpError() << "'" << stringifyLinkage(getLinkage())
                         << "' linkage not supported in ifuncs, available "
                            "options: private, internal, linkonce, weak, "
                            "linkonce_odr, weak_odr, or external linkage";
  }
  return success();
}

//===----------------------------------------------------------------------===//
// ShuffleVectorOp
//===----------------------------------------------------------------------===//

void ShuffleVectorOp::build(OpBuilder &builder, OperationState &state, Value v1,
                            Value v2, DenseI32ArrayAttr mask,
                            ArrayRef<NamedAttribute> attrs) {
  auto containerType = v1.getType();
  auto vType = LLVM::getVectorType(
      cast<VectorType>(containerType).getElementType(), mask.size(),
      LLVM::isScalableVectorType(containerType));
  build(builder, state, vType, v1, v2, mask);
  state.addAttributes(attrs);
}

void ShuffleVectorOp::build(OpBuilder &builder, OperationState &state, Value v1,
                            Value v2, ArrayRef<int32_t> mask) {
  build(builder, state, v1, v2, builder.getDenseI32ArrayAttr(mask));
}

/// Build the result type of a shuffle vector operation.
static ParseResult parseShuffleType(AsmParser &parser, Type v1Type,
                                    Type &resType, DenseI32ArrayAttr mask) {
  if (!LLVM::isCompatibleVectorType(v1Type))
    return parser.emitError(parser.getCurrentLocation(),
                            "expected an LLVM compatible vector type");
  resType =
      LLVM::getVectorType(cast<VectorType>(v1Type).getElementType(),
                          mask.size(), LLVM::isScalableVectorType(v1Type));
  return success();
}

/// Nothing to do when the result type is inferred.
static void printShuffleType(AsmPrinter &printer, Operation *op, Type v1Type,
                             Type resType, DenseI32ArrayAttr mask) {}

LogicalResult ShuffleVectorOp::verify() {
  if (LLVM::isScalableVectorType(getV1().getType()) &&
      llvm::any_of(getMask(), [](int32_t v) { return v != 0; }))
    return emitOpError("expected a splat operation for scalable vectors");
  return success();
}

// Folding for shufflevector op when v1 is single element 1D vector
// and the mask is a single zero. OpFoldResult will be v1 in this case.
OpFoldResult ShuffleVectorOp::fold(FoldAdaptor adaptor) {
  // Check if operand 0 is a single element vector.
  auto vecType = llvm::dyn_cast<VectorType>(getV1().getType());
  if (!vecType || vecType.getRank() != 1 || vecType.getNumElements() != 1)
    return {};
  // Check if the mask is a single zero.
  // Note: The mask is guaranteed to be non-empty.
  if (getMask().size() != 1 || getMask()[0] != 0)
    return {};
  return getV1();
}

//===----------------------------------------------------------------------===//
// Implementations for LLVM::LLVMFuncOp.
//===----------------------------------------------------------------------===//

// Add the entry block to the function.
Block *LLVMFuncOp::addEntryBlock(OpBuilder &builder) {
  assert(empty() && "function already has an entry block");
  OpBuilder::InsertionGuard g(builder);
  Block *entry = builder.createBlock(&getBody());

  // FIXME: Allow passing in proper locations for the entry arguments.
  LLVMFunctionType type = getFunctionType();
  for (unsigned i = 0, e = type.getNumParams(); i < e; ++i)
    entry->addArgument(type.getParamType(i), getLoc());
  return entry;
}

void LLVMFuncOp::build(OpBuilder &builder, OperationState &result,
                       StringRef name, Type type, LLVM::Linkage linkage,
                       bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
                       ArrayRef<NamedAttribute> attrs,
                       ArrayRef<DictionaryAttr> argAttrs,
                       std::optional<uint64_t> functionEntryCount) {
  result.addRegion();
  result.addAttribute(SymbolTable::getSymbolAttrName(),
                      builder.getStringAttr(name));
  result.addAttribute(getFunctionTypeAttrName(result.name),
                      TypeAttr::get(type));
  result.addAttribute(getLinkageAttrName(result.name),
                      LinkageAttr::get(builder.getContext(), linkage));
  result.addAttribute(getCConvAttrName(result.name),
                      CConvAttr::get(builder.getContext(), cconv));
  result.attributes.append(attrs.begin(), attrs.end());
  if (dsoLocal)
    result.addAttribute(getDsoLocalAttrName(result.name),
                        builder.getUnitAttr());
  if (comdat)
    result.addAttribute(getComdatAttrName(result.name), comdat);
  if (functionEntryCount)
    result.addAttribute(getFunctionEntryCountAttrName(result.name),
                        FunctionEntryCountAttr::get(
                            builder.getContext(), *functionEntryCount,
                            ProfileCountType::Real, ArrayRef<uint64_t>{}));
#ifndef NDEBUG
  std::optional<NamedAttribute> duplicate = result.attributes.findDuplicate();
  if (duplicate.has_value()) {
    llvm::report_fatal_error(
        Twine("LLVMFuncOp propagated an attribute that is meant "
              "to be constructed by the builder: ") +
        duplicate->getName().str());
  }
#endif
  if (argAttrs.empty())
    return;

  assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
         "expected as many argument attribute lists as arguments");
  call_interface_impl::addArgAndResultAttrs(
      builder, result, argAttrs, /*resultAttrs=*/{},
      getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
}

// Builds an LLVM function type from the given lists of input and output types.
// Returns a null type if any of the types provided are non-LLVM types, or if
// there is more than one output type.
static Type
buildLLVMFunctionType(OpAsmParser &parser, SMLoc loc, ArrayRef<Type> inputs,
                      ArrayRef<Type> outputs,
                      function_interface_impl::VariadicFlag variadicFlag) {
  Builder &b = parser.getBuilder();
  if (outputs.size() > 1) {
    parser.emitError(loc, "failed to construct function type: expected zero or "
                          "one function result");
    return {};
  }

  // Convert inputs to LLVM types, exit early on error.
  SmallVector<Type, 4> llvmInputs;
  for (auto t : inputs) {
    if (!isCompatibleType(t)) {
      parser.emitError(loc, "failed to construct function type: expected LLVM "
                            "type for function arguments");
      return {};
    }
    llvmInputs.push_back(t);
  }

  // No output is denoted as "void" in LLVM type system.
  Type llvmOutput =
      outputs.empty() ? LLVMVoidType::get(b.getContext()) : outputs.front();
  if (!isCompatibleType(llvmOutput)) {
    parser.emitError(loc, "failed to construct function type: expected LLVM "
                          "type for function results")
        << llvmOutput;
    return {};
  }
  return LLVMFunctionType::get(llvmOutput, llvmInputs,
                               variadicFlag.isVariadic());
}

// Parses an LLVM function.
//
// operation ::= `llvm.func` linkage? cconv? function-signature
//                (`comdat(` symbol-ref-id `)`)?
//                function-attributes?
//                function-body
//
ParseResult LLVMFuncOp::parse(OpAsmParser &parser, OperationState &result) {
  // Default to external linkage if no keyword is provided.
  result.addAttribute(getLinkageAttrName(result.name),
                      LinkageAttr::get(parser.getContext(),
                                       parseOptionalLLVMKeyword<Linkage>(
                                           parser, LLVM::Linkage::External)));

  // Parse optional visibility, default to Default.
  result.addAttribute(getVisibility_AttrName(result.name),
                      parser.getBuilder().getI64IntegerAttr(
                          parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
                              parser, LLVM::Visibility::Default)));

  // Parse optional UnnamedAddr, default to None.
  result.addAttribute(getUnnamedAddrAttrName(result.name),
                      parser.getBuilder().getI64IntegerAttr(
                          parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
                              parser, LLVM::UnnamedAddr::None)));

  // Default to C Calling Convention if no keyword is provided.
  result.addAttribute(
      getCConvAttrName(result.name),
      CConvAttr::get(parser.getContext(),
                     parseOptionalLLVMKeyword<CConv>(parser, LLVM::CConv::C)));

  StringAttr nameAttr;
  SmallVector<OpAsmParser::Argument> entryArgs;
  SmallVector<DictionaryAttr> resultAttrs;
  SmallVector<Type> resultTypes;
  bool isVariadic;

  auto signatureLocation = parser.getCurrentLocation();
  if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
                             result.attributes) ||
      function_interface_impl::parseFunctionSignatureWithArguments(
          parser, /*allowVariadic=*/true, entryArgs, isVariadic, resultTypes,
          resultAttrs))
    return failure();

  SmallVector<Type> argTypes;
  for (auto &arg : entryArgs)
    argTypes.push_back(arg.type);
  auto type =
      buildLLVMFunctionType(parser, signatureLocation, argTypes, resultTypes,
                            function_interface_impl::VariadicFlag(isVariadic));
  if (!type)
    return failure();
  result.addAttribute(getFunctionTypeAttrName(result.name),
                      TypeAttr::get(type));

  if (succeeded(parser.parseOptionalKeyword("vscale_range"))) {
    int64_t minRange, maxRange;
    if (parser.parseLParen() || parser.parseInteger(minRange) ||
        parser.parseComma() || parser.parseInteger(maxRange) ||
        parser.parseRParen())
      return failure();
    auto intTy = IntegerType::get(parser.getContext(), 32);
    result.addAttribute(
        getVscaleRangeAttrName(result.name),
        LLVM::VScaleRangeAttr::get(parser.getContext(),
                                   IntegerAttr::get(intTy, minRange),
                                   IntegerAttr::get(intTy, maxRange)));
  }
  // Parse the optional comdat selector.
  if (succeeded(parser.parseOptionalKeyword("comdat"))) {
    SymbolRefAttr comdat;
    if (parser.parseLParen() || parser.parseAttribute(comdat) ||
        parser.parseRParen())
      return failure();

    result.addAttribute(getComdatAttrName(result.name), comdat);
  }

  if (failed(parser.parseOptionalAttrDictWithKeyword(result.attributes)))
    return failure();
  call_interface_impl::addArgAndResultAttrs(
      parser.getBuilder(), result, entryArgs, resultAttrs,
      getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));

  auto *body = result.addRegion();
  OptionalParseResult parseResult =
      parser.parseOptionalRegion(*body, entryArgs);
  return failure(parseResult.has_value() && failed(*parseResult));
}

// Print the LLVMFuncOp. Collects argument and result types and passes them to
// helper functions. Drops "void" result since it cannot be parsed back. Skips
// the external linkage since it is the default value.
void LLVMFuncOp::print(OpAsmPrinter &p) {
  p << ' ';
  if (getLinkage() != LLVM::Linkage::External)
    p << stringifyLinkage(getLinkage()) << ' ';
  StringRef visibility = stringifyVisibility(getVisibility_());
  if (!visibility.empty())
    p << visibility << ' ';
  if (auto unnamedAddr = getUnnamedAddr()) {
    StringRef str = stringifyUnnamedAddr(*unnamedAddr);
    if (!str.empty())
      p << str << ' ';
  }
  if (getCConv() != LLVM::CConv::C)
    p << stringifyCConv(getCConv()) << ' ';

  p.printSymbolName(getName());

  LLVMFunctionType fnType = getFunctionType();
  SmallVector<Type, 8> argTypes;
  SmallVector<Type, 1> resTypes;
  argTypes.reserve(fnType.getNumParams());
  for (unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
    argTypes.push_back(fnType.getParamType(i));

  Type returnType = fnType.getReturnType();
  if (!llvm::isa<LLVMVoidType>(returnType))
    resTypes.push_back(returnType);

  function_interface_impl::printFunctionSignature(p, *this, argTypes,
                                                  isVarArg(), resTypes);

  // Print vscale range if present
  if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
    p << " vscale_range(" << vscale->getMinRange().getInt() << ", "
      << vscale->getMaxRange().getInt() << ')';

  // Print the optional comdat selector.
  if (auto comdat = getComdat())
    p << " comdat(" << *comdat << ')';

  function_interface_impl::printFunctionAttributes(
      p, *this,
      {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
       getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
       getComdatAttrName(), getUnnamedAddrAttrName(),
       getVscaleRangeAttrName()});

  // Print the body if this is not an external function.
  Region &body = getBody();
  if (!body.empty()) {
    p << ' ';
    p.printRegion(body, /*printEntryBlockArgs=*/false,
                  /*printBlockTerminators=*/true);
  }
}

// Verifies LLVM- and implementation-specific properties of the LLVM func Op:
// - functions don't have 'common' linkage
// - external functions have 'external' or 'extern_weak' linkage;
// - vararg is (currently) only supported for external functions;
LogicalResult LLVMFuncOp::verify() {
  if (getLinkage() == LLVM::Linkage::Common)
    return emitOpError() << "functions cannot have '"
                         << stringifyLinkage(LLVM::Linkage::Common)
                         << "' linkage";

  if (failed(verifyComdat(*this, getComdat())))
    return failure();

  if (isExternal()) {
    if (getLinkage() != LLVM::Linkage::External &&
        getLinkage() != LLVM::Linkage::ExternWeak)
      return emitOpError() << "external functions must have '"
                           << stringifyLinkage(LLVM::Linkage::External)
                           << "' or '"
                           << stringifyLinkage(LLVM::Linkage::ExternWeak)
                           << "' linkage";
    return success();
  }

  // In LLVM IR, these attributes are composed by convention, not by design.
  if (isNoInline() && isAlwaysInline())
    return emitError("no_inline and always_inline attributes are incompatible");

  if (isOptimizeNone() && !isNoInline())
    return emitOpError("with optimize_none must also be no_inline");

  Type landingpadResultTy;
  StringRef diagnosticMessage;
  bool isLandingpadTypeConsistent =
      !walk([&](Operation *op) {
         const auto checkType = [&](Type type, StringRef errorMessage) {
           if (!landingpadResultTy) {
             landingpadResultTy = type;
             return WalkResult::advance();
           }
           if (landingpadResultTy != type) {
             diagnosticMessage = errorMessage;
             return WalkResult::interrupt();
           }
           return WalkResult::advance();
         };
         return TypeSwitch<Operation *, WalkResult>(op)
             .Case([&](LandingpadOp landingpad) {
               constexpr StringLiteral errorMessage =
                   "'llvm.landingpad' should have a consistent result type "
                   "inside a function";
               return checkType(landingpad.getType(), errorMessage);
             })
             .Case([&](ResumeOp resume) {
               constexpr StringLiteral errorMessage =
                   "'llvm.resume' should have a consistent input type inside a "
                   "function";
               return checkType(resume.getValue().getType(), errorMessage);
             })
             .Default([](auto) { return WalkResult::skip(); });
       }).wasInterrupted();
  if (!isLandingpadTypeConsistent) {
    assert(!diagnosticMessage.empty() &&
           "Expecting a non-empty diagnostic message");
    return emitError(diagnosticMessage);
  }

  if (failed(verifyBlockTags(*this)))
    return failure();

  return success();
}

/// Verifies LLVM- and implementation-specific properties of the LLVM func Op:
/// - entry block arguments are of LLVM types.
LogicalResult LLVMFuncOp::verifyRegions() {
  if (isExternal())
    return success();

  unsigned numArguments = getFunctionType().getNumParams();
  Block &entryBlock = front();
  for (unsigned i = 0; i < numArguments; ++i) {
    Type argType = entryBlock.getArgument(i).getType();
    if (!isCompatibleType(argType))
      return emitOpError("entry block argument #")
             << i << " is not of LLVM type";
  }

  return success();
}

Region *LLVMFuncOp::getCallableRegion() {
  if (isExternal())
    return nullptr;
  return &getBody();
}

//===----------------------------------------------------------------------===//
// UndefOp.
//===----------------------------------------------------------------------===//

/// Fold an undef operation to a dedicated undef attribute.
OpFoldResult LLVM::UndefOp::fold(FoldAdaptor) {
  return LLVM::UndefAttr::get(getContext());
}

//===----------------------------------------------------------------------===//
// PoisonOp.
//===----------------------------------------------------------------------===//

/// Fold a poison operation to a dedicated poison attribute.
OpFoldResult LLVM::PoisonOp::fold(FoldAdaptor) {
  return LLVM::PoisonAttr::get(getContext());
}

//===----------------------------------------------------------------------===//
// MetadataAsValueOp.
//===----------------------------------------------------------------------===//

/// Fold a metadata-as-value operation to its wrapped metadata attribute.
OpFoldResult LLVM::MetadataAsValueOp::fold(FoldAdaptor) {
  return getMetadataAttr();
}

//===----------------------------------------------------------------------===//
// ZeroOp.
//===----------------------------------------------------------------------===//

LogicalResult LLVM::ZeroOp::verify() {
  if (auto targetExtType = dyn_cast<LLVMTargetExtType>(getType()))
    if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
      return emitOpError()
             << "target extension type does not support zero-initializer";

  return success();
}

/// Fold a zero operation to a builtin zero attribute when possible and fall
/// back to a dedicated zero attribute.
OpFoldResult LLVM::ZeroOp::fold(FoldAdaptor) {
  OpFoldResult result = Builder(getContext()).getZeroAttr(getType());
  if (result)
    return result;
  return LLVM::ZeroAttr::get(getContext());
}

//===----------------------------------------------------------------------===//
// ConstantOp.
//===----------------------------------------------------------------------===//

/// Compute the total number of elements in the given type, also taking into
/// account nested types. Supported types are `VectorType` and `LLVMArrayType`.
/// Everything else is treated as a scalar.
static int64_t getNumElements(Type t) {
  if (auto vecType = dyn_cast<VectorType>(t)) {
    assert(!vecType.isScalable() &&
           "number of elements of a scalable vector type is unknown");
    return vecType.getNumElements() * getNumElements(vecType.getElementType());
  }
  if (auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
    return arrayType.getNumElements() *
           getNumElements(arrayType.getElementType());
  return 1;
}

/// Determine the element type of `type`. Supported types are `VectorType`,
/// `TensorType`, and `LLVMArrayType`. Everything else is treated as a scalar.
static Type getElementType(Type type) {
  while (auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
    type = arrayType.getElementType();
  if (auto vecType = dyn_cast<VectorType>(type))
    return vecType.getElementType();
  if (auto tenType = dyn_cast<TensorType>(type))
    return tenType.getElementType();
  return type;
}

/// Check if the given type is a scalable vector type or a vector/array type
/// that contains a nested scalable vector type.
static bool hasScalableVectorType(Type t) {
  if (auto vecType = dyn_cast<VectorType>(t)) {
    if (vecType.isScalable())
      return true;
    return hasScalableVectorType(vecType.getElementType());
  }
  if (auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
    return hasScalableVectorType(arrayType.getElementType());
  return false;
}

/// Verifies the constant array represented by `arrayAttr` matches the provided
/// `arrayType`.
static LogicalResult verifyStructArrayConstant(LLVM::ConstantOp op,
                                               LLVM::LLVMArrayType arrayType,
                                               ArrayAttr arrayAttr, int dim) {
  if (arrayType.getNumElements() != arrayAttr.size())
    return op.emitOpError()
           << "array attribute size does not match array type size in "
              "dimension "
           << dim << ": " << arrayAttr.size() << " vs. "
           << arrayType.getNumElements();

  llvm::DenseSet<Attribute> elementsVerified;

  // Recursively verify sub-dimensions for multidimensional arrays.
  if (auto subArrayType =
          dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
    for (auto [idx, elementAttr] : llvm::enumerate(arrayAttr))
      if (elementsVerified.insert(elementAttr).second) {
        if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
          continue;
        auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
        if (!subArrayAttr)
          return op.emitOpError()
                 << "nested attribute for sub-array in dimension " << dim
                 << " at index " << idx
                 << " must be a zero, or undef, or array attribute";
        if (failed(verifyStructArrayConstant(op, subArrayType, subArrayAttr,
                                             dim + 1)))
          return failure();
      }
    return success();
  }

  // Forbid usages of ArrayAttr for simple array types that should use
  // DenseElementsAttr instead. Note that there would be a use case for such
  // array types when one element value is obtained via a ptr-to-int conversion
  // from a symbol and cannot be represented in a DenseElementsAttr, but no MLIR
  // user needs this so far, and it seems better to avoid people misusing the
  // ArrayAttr for simple types.
  Type elementType = arrayType.getElementType();
  if (isa<LLVM::LLVMPointerType>(elementType)) {
    for (auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
      if (isa<FlatSymbolRefAttr, LLVM::ZeroAttr, LLVM::UndefAttr,
              LLVM::PoisonAttr>(elementAttr))
        continue;
      return op.emitOpError()
             << "pointer array element at index " << idx
             << " must be a flat symbol reference, zero, undef, or poison";
    }
    return success();
  }
  auto structType = dyn_cast<LLVM::LLVMStructType>(elementType);
  if (!structType)
    return op.emitOpError() << "for array with an array attribute must have a "
                               "struct element type";

  // Shallow verification that leaf attributes are appropriate as struct initial
  // value.
  size_t numStructElements = structType.getBody().size();
  for (auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
    if (elementsVerified.insert(elementAttr).second) {
      if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
        continue;
      auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
      if (!subArrayAttr)
        return op.emitOpError()
               << "nested attribute for struct element at index " << idx
               << " must be a zero, or undef, or array attribute";
      if (subArrayAttr.size() != numStructElements)
        return op.emitOpError()
               << "nested array attribute size for struct element at index "
               << idx << " must match struct size: " << subArrayAttr.size()
               << " vs. " << numStructElements;
    }
  }

  return success();
}

LogicalResult LLVM::ConstantOp::verify() {
  if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
    auto arrayType = llvm::dyn_cast<LLVMArrayType>(getType());
    if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
        !arrayType.getElementType().isInteger(8)) {
      return emitOpError() << "expected array type of "
                           << sAttr.getValue().size()
                           << " i8 elements for the string constant";
    }
    return success();
  }
  if (auto structType = dyn_cast<LLVMStructType>(getType())) {
    auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
    if (!arrayAttr)
      return emitOpError() << "expected array attribute for struct type";

    ArrayRef<Type> elementTypes = structType.getBody();
    if (arrayAttr.size() != elementTypes.size()) {
      return emitOpError() << "expected array attribute of size "
                           << elementTypes.size();
    }
    for (auto [i, attr, type] : llvm::enumerate(arrayAttr, elementTypes)) {
      if (!type.isSignlessIntOrIndexOrFloat()) {
        return emitOpError() << "expected struct element types to be floating "
                                "point type or integer type";
      }
      if (!isa<FloatAttr, IntegerAttr>(attr)) {
        return emitOpError() << "expected element of array attribute to be "
                                "floating point or integer";
      }
      if (cast<TypedAttr>(attr).getType() != type)
        return emitOpError()
               << "struct element at index " << i << " is of wrong type";
    }

    return success();
  }
  if (auto targetExtType = dyn_cast<LLVMTargetExtType>(getType()))
    return emitOpError() << "does not support target extension type.";

  // Check that an attribute whose element type has floating point semantics
  // `attributeFloatSemantics` is compatible with a type whose element type
  // is `constantElementType`.
  //
  // Requirement is that either
  // 1) They have identical floating point types.
  // 2) `constantElementType` is an integer type of the same width as the float
  //     attribute. This is to support builtin MLIR float types without LLVM
  //     equivalents, see comments in getLLVMConstant for more details.
  auto verifyFloatSemantics =
      [this](const llvm::fltSemantics &attributeFloatSemantics,
             Type constantElementType) -> LogicalResult {
    if (auto floatType = dyn_cast<FloatType>(constantElementType)) {
      if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
        return emitOpError()
               << "attribute and type have different float semantics";
      }
      return success();
    }
    unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
    if (isa<IntegerType>(constantElementType)) {
      if (!constantElementType.isInteger(floatWidth))
        return emitOpError() << "expected integer type of width " << floatWidth;

      return success();
    }
    return success();
  };

  // Verification of IntegerAttr, FloatAttr, ElementsAttr, ArrayAttr.
  if (isa<IntegerAttr>(getValue())) {
    if (!llvm::isa<IntegerType>(getType()))
      return emitOpError() << "expected integer type";
  } else if (auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
    return verifyFloatSemantics(floatAttr.getValue().getSemantics(), getType());
  } else if (auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
    if (hasScalableVectorType(getType())) {
      // The exact number of elements of a scalable vector is unknown, so we
      // allow only splat attributes.
      auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
      if (!splatElementsAttr)
        return emitOpError()
               << "scalable vector type requires a splat attribute";
      return success();
    }
    if (!isa<VectorType, LLVM::LLVMArrayType>(getType()))
      return emitOpError() << "expected vector or array type";

    // The number of elements of the attribute and the type must match.
    int64_t attrNumElements = elementsAttr.getNumElements();
    if (getNumElements(getType()) != attrNumElements) {
      return emitOpError()
             << "type and attribute have a different number of elements: "
             << getNumElements(getType()) << " vs. " << attrNumElements;
    }

    Type attrElmType = getElementType(elementsAttr.getType());
    Type resultElmType = getElementType(getType());
    if (auto floatType = dyn_cast<FloatType>(attrElmType))
      return verifyFloatSemantics(floatType.getFloatSemantics(), resultElmType);

    if (isa<IntegerType>(attrElmType) && !isa<IntegerType>(resultElmType)) {
      return emitOpError(
          "expected integer element type for integer elements attribute");
    }
  } else if (auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {

    // The case where the constant is LLVMStructType has already been handled.
    auto arrayType = dyn_cast<LLVM::LLVMArrayType>(getType());
    if (!arrayType)
      return emitOpError()
             << "expected array or struct type for array attribute";

    // When the attribute is an ArrayAttr, check that its nesting matches the
    // corresponding ArrayType or VectorType nesting.
    return verifyStructArrayConstant(*this, arrayType, arrayAttr, /*dim=*/0);
  } else {
    return emitOpError()
           << "only supports integer, float, string or elements attributes";
  }

  return success();
}

bool LLVM::ConstantOp::isBuildableWith(Attribute value, Type type) {
  // The value's type must be the same as the provided type.
  auto typedAttr = dyn_cast<TypedAttr>(value);
  if (!typedAttr || typedAttr.getType() != type || !isCompatibleType(type))
    return false;
  // The value's type must be an LLVM compatible type.
  if (!isCompatibleType(type))
    return false;
  // TODO: Add support for additional attributes kinds once needed.
  return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
}

ConstantOp LLVM::ConstantOp::materialize(OpBuilder &builder, Attribute value,
                                         Type type, Location loc) {
  if (isBuildableWith(value, type))
    return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
  return nullptr;
}

// Constant op constant-folds to its value.
OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) { return getValue(); }

//===----------------------------------------------------------------------===//
// AtomicRMWOp
//===----------------------------------------------------------------------===//

void AtomicRMWOp::build(OpBuilder &builder, OperationState &state,
                        AtomicBinOp binOp, Value ptr, Value val,
                        AtomicOrdering ordering, StringRef syncscope,
                        unsigned alignment, bool isVolatile) {
  build(builder, state, val.getType(), binOp, ptr, val, ordering,
        !syncscope.empty() ? builder.getStringAttr(syncscope) : nullptr,
        alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isVolatile,
        /*access_groups=*/nullptr,
        /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
}

LogicalResult AtomicRMWOp::verify() {
  auto valType = getVal().getType();
  if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
      getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
      getBinOp() == AtomicBinOp::fminimum ||
      getBinOp() == AtomicBinOp::fmaximum ||
      getBinOp() == AtomicBinOp::fminimumnum ||
      getBinOp() == AtomicBinOp::fmaximumnum) {
    if (isCompatibleVectorType(valType)) {
      if (isScalableVectorType(valType))
        return emitOpError("expected LLVM IR fixed vector type");
      Type elemType = llvm::cast<VectorType>(valType).getElementType();
      if (!isCompatibleFloatingPointType(elemType))
        return emitOpError(
            "expected LLVM IR floating point type for vector element");
    } else if (!isCompatibleFloatingPointType(valType)) {
      return emitOpError("expected LLVM IR floating point type");
    }
  } else if (getBinOp() == AtomicBinOp::xchg) {
    DataLayout dataLayout = DataLayout::closest(*this);
    if (!isTypeCompatibleWithAtomicOp(valType, dataLayout))
      return emitOpError("unexpected LLVM IR type for 'xchg' bin_op");
  } else {
    auto intType = llvm::dyn_cast<IntegerType>(valType);
    unsigned intBitWidth = intType ? intType.getWidth() : 0;
    if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
        intBitWidth != 64)
      return emitOpError("expected LLVM IR integer type");
  }

  if (static_cast<unsigned>(getOrdering()) <
      static_cast<unsigned>(AtomicOrdering::monotonic))
    return emitOpError() << "expected at least '"
                         << stringifyAtomicOrdering(AtomicOrdering::monotonic)
                         << "' ordering";

  return success();
}

//===----------------------------------------------------------------------===//
// AtomicCmpXchgOp
//===----------------------------------------------------------------------===//

/// Returns an LLVM struct type that contains a value type and a boolean type.
static LLVMStructType getValAndBoolStructType(Type valType) {
  auto boolType = IntegerType::get(valType.getContext(), 1);
  return LLVMStructType::getLiteral(valType.getContext(), {valType, boolType});
}

void AtomicCmpXchgOp::build(OpBuilder &builder, OperationState &state,
                            Value ptr, Value cmp, Value val,
                            AtomicOrdering successOrdering,
                            AtomicOrdering failureOrdering, StringRef syncscope,
                            unsigned alignment, bool isWeak, bool isVolatile) {
  build(builder, state, getValAndBoolStructType(val.getType()), ptr, cmp, val,
        successOrdering, failureOrdering,
        !syncscope.empty() ? builder.getStringAttr(syncscope) : nullptr,
        alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isWeak,
        isVolatile, /*access_groups=*/nullptr,
        /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
}

LogicalResult AtomicCmpXchgOp::verify() {
  auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().getType());
  if (!ptrType)
    return emitOpError("expected LLVM IR pointer type for operand #0");
  auto valType = getVal().getType();
  DataLayout dataLayout = DataLayout::closest(*this);
  if (!isTypeCompatibleWithAtomicOp(valType, dataLayout))
    return emitOpError("unexpected LLVM IR type");
  if (getSuccessOrdering() < AtomicOrdering::monotonic ||
      getFailureOrdering() < AtomicOrdering::monotonic)
    return emitOpError("ordering must be at least 'monotonic'");
  if (getFailureOrdering() == AtomicOrdering::release ||
      getFailureOrdering() == AtomicOrdering::acq_rel)
    return emitOpError("failure ordering cannot be 'release' or 'acq_rel'");
  return success();
}

//===----------------------------------------------------------------------===//
// FenceOp
//===----------------------------------------------------------------------===//

void FenceOp::build(OpBuilder &builder, OperationState &state,
                    AtomicOrdering ordering, StringRef syncscope) {
  build(builder, state, ordering,
        syncscope.empty() ? nullptr : builder.getStringAttr(syncscope));
}

LogicalResult FenceOp::verify() {
  if (getOrdering() == AtomicOrdering::not_atomic ||
      getOrdering() == AtomicOrdering::unordered ||
      getOrdering() == AtomicOrdering::monotonic)
    return emitOpError("can be given only acquire, release, acq_rel, "
                       "and seq_cst orderings");
  return success();
}

//===----------------------------------------------------------------------===//
// Verifier for extension ops
//===----------------------------------------------------------------------===//

/// Verifies that the given extension operation operates on consistent scalars
/// or vectors, and that the target width is larger than the input width.
template <class ExtOp>
static LogicalResult verifyExtOp(ExtOp op) {
  IntegerType inputType, outputType;
  if (isCompatibleVectorType(op.getArg().getType())) {
    if (!isCompatibleVectorType(op.getResult().getType()))
      return op.emitError(
          "input type is a vector but output type is an integer");
    if (getVectorNumElements(op.getArg().getType()) !=
        getVectorNumElements(op.getResult().getType()))
      return op.emitError("input and output vectors are of incompatible shape");
    // Because this is a CastOp, the element of vectors is guaranteed to be an
    // integer.
    inputType = cast<IntegerType>(
        cast<VectorType>(op.getArg().getType()).getElementType());
    outputType = cast<IntegerType>(
        cast<VectorType>(op.getResult().getType()).getElementType());
  } else {
    // Because this is a CastOp and arg is not a vector, arg is guaranteed to be
    // an integer.
    inputType = cast<IntegerType>(op.getArg().getType());
    outputType = dyn_cast<IntegerType>(op.getResult().getType());
    if (!outputType)
      return op.emitError(
          "input type is an integer but output type is a vector");
  }

  if (outputType.getWidth() <= inputType.getWidth())
    return op.emitError("integer width of the output type is smaller or "
                        "equal to the integer width of the input type");
  return success();
}

//===----------------------------------------------------------------------===//
// ZExtOp
//===----------------------------------------------------------------------===//

LogicalResult ZExtOp::verify() { return verifyExtOp<ZExtOp>(*this); }

OpFoldResult LLVM::ZExtOp::fold(FoldAdaptor adaptor) {
  auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
  if (!arg)
    return {};

  size_t targetSize = cast<IntegerType>(getType()).getWidth();
  return IntegerAttr::get(getType(), arg.getValue().zext(targetSize));
}

//===----------------------------------------------------------------------===//
// SExtOp
//===----------------------------------------------------------------------===//

LogicalResult SExtOp::verify() { return verifyExtOp<SExtOp>(*this); }

//===----------------------------------------------------------------------===//
// Folder and verifier for LLVM::BitcastOp
//===----------------------------------------------------------------------===//

/// Folds a cast op that can be chained.
template <typename T>
static OpFoldResult foldChainableCast(T castOp,
                                      typename T::FoldAdaptor adaptor) {
  // cast(x : T0, T0) -> x
  if (castOp.getArg().getType() == castOp.getType())
    return castOp.getArg();
  if (auto prev = castOp.getArg().template getDefiningOp<T>()) {
    // cast(cast(x : T0, T1), T0) -> x
    if (prev.getArg().getType() == castOp.getType())
      return prev.getArg();
    // cast(cast(x : T0, T1), T2) -> cast(x: T0, T2)
    castOp.getArgMutable().set(prev.getArg());
    return Value{castOp};
  }
  return {};
}

OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
  return foldChainableCast(*this, adaptor);
}

LogicalResult LLVM::BitcastOp::verify() {
  Type srcElemType = extractVectorElementType(getArg().getType());
  Type dstElemType = extractVectorElementType(getResult().getType());

  // TODO: 'bitcast' requires result and operand type to be identical in size.
  // Byte types may be cast from/to any type pointer constraints.
  if (isa<LLVMByteType>(srcElemType) || isa<LLVMByteType>(dstElemType))
    return success();

  auto resultType = llvm::dyn_cast<LLVMPointerType>(dstElemType);
  auto sourceType = llvm::dyn_cast<LLVMPointerType>(srcElemType);

  // If one of the types is a pointer (or vector of pointers), then
  // both source and result type have to be pointers.
  if (static_cast<bool>(resultType) != static_cast<bool>(sourceType))
    return emitOpError("can only cast pointers from and to pointers");

  if (!resultType)
    return success();

  auto isVector = llvm::IsaPred<VectorType>;

  // Due to bitcast requiring both operands to be of the same size, it is not
  // possible for only one of the two to be a pointer of vectors.
  if (isVector(getResult().getType()) && !isVector(getArg().getType()))
    return emitOpError("cannot cast pointer to vector of pointers");

  if (!isVector(getResult().getType()) && isVector(getArg().getType()))
    return emitOpError("cannot cast vector of pointers to pointer");

  // Bitcast cannot cast between pointers of different address spaces.
  // 'llvm.addrspacecast' must be used for this purpose instead.
  if (resultType.getAddressSpace() != sourceType.getAddressSpace())
    return emitOpError("cannot cast pointers of different address spaces, "
                       "use 'llvm.addrspacecast' instead");

  return success();
}

LogicalResult LLVM::PtrToAddrOp::verify() {
  auto pointerType =
      cast<LLVM::LLVMPointerType>(extractVectorElementType(getArg().getType()));
  auto integerType = cast<IntegerType>(extractVectorElementType(getType()));

  auto dataLayout = DataLayout::closest(*this);
  std::optional<unsigned> width = dataLayout.getTypeIndexBitwidth(pointerType);
  assert(width && "pointers always return an index bitwidth");
  if (width != integerType.getWidth())
    return emitOpError("bit-width of integer result type ")
           << integerType << " must match the pointer bitwidth (" << *width
           << ") specified in the datalayout";

  return success();
}

//===----------------------------------------------------------------------===//
// Folder for LLVM::AddrSpaceCastOp
//===----------------------------------------------------------------------===//

OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
  return foldChainableCast(*this, adaptor);
}

Value LLVM::AddrSpaceCastOp::getViewSource() { return getArg(); }

//===----------------------------------------------------------------------===//
// Folder for LLVM::GEPOp
//===----------------------------------------------------------------------===//

OpFoldResult LLVM::GEPOp::fold(FoldAdaptor adaptor) {
  GEPIndicesAdaptor<ArrayRef<Attribute>> indices(getRawConstantIndicesAttr(),
                                                 adaptor.getDynamicIndices());

  // gep %x:T, 0 -> %x
  if (getBase().getType() == getType() && indices.size() == 1)
    if (auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
      if (integer.getValue().isZero())
        return getBase();

  // Canonicalize any dynamic indices of constant value to constant indices.
  bool changed = false;
  SmallVector<GEPArg> gepArgs;
  for (auto iter : llvm::enumerate(indices)) {
    auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
    // Constant indices can only be int32_t, so if integer does not fit we
    // are forced to keep it dynamic, despite being a constant.
    if (!indices.isDynamicIndex(iter.index()) || !integer ||
        !integer.getValue().isSignedIntN(kGEPConstantBitWidth)) {

      PointerUnion<IntegerAttr, Value> existing = getIndices()[iter.index()];
      if (Value val = llvm::dyn_cast_if_present<Value>(existing))
        gepArgs.emplace_back(val);
      else
        gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());

      continue;
    }

    changed = true;
    gepArgs.emplace_back(integer.getInt());
  }
  if (changed) {
    SmallVector<int32_t> rawConstantIndices;
    SmallVector<Value> dynamicIndices;
    destructureIndices(getElemType(), gepArgs, rawConstantIndices,
                       dynamicIndices);

    getDynamicIndicesMutable().assign(dynamicIndices);
    setRawConstantIndices(rawConstantIndices);
    return Value{*this};
  }

  return {};
}

Value LLVM::GEPOp::getViewSource() { return getBase(); }

//===----------------------------------------------------------------------===//
// ShlOp
//===----------------------------------------------------------------------===//

OpFoldResult LLVM::ShlOp::fold(FoldAdaptor adaptor) {
  auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
  if (!rhs)
    return {};

  if (rhs.getValue().getZExtValue() >=
      getLhs().getType().getIntOrFloatBitWidth())
    return {}; // TODO: Fold into poison.

  auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
  if (!lhs)
    return {};

  return IntegerAttr::get(getType(), lhs.getValue().shl(rhs.getValue()));
}

//===----------------------------------------------------------------------===//
// OrOp
//===----------------------------------------------------------------------===//

OpFoldResult LLVM::OrOp::fold(FoldAdaptor adaptor) {
  auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
  if (!lhs)
    return {};

  auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
  if (!rhs)
    return {};

  return IntegerAttr::get(getType(), lhs.getValue() | rhs.getValue());
}

//===----------------------------------------------------------------------===//
// CallIntrinsicOp
//===----------------------------------------------------------------------===//

LogicalResult CallIntrinsicOp::verify() {
  if (!getIntrin().starts_with("llvm."))
    return emitOpError() << "intrinsic name must start with 'llvm.'";
  if (failed(verifyOperandBundles(*this)))
    return failure();
  return success();
}

void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
                            mlir::StringAttr intrin, mlir::ValueRange args) {
  build(builder, state, /*resultTypes=*/TypeRange{}, intrin, args,
        FastmathFlagsAttr{},
        /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{}, /*arg_attrs=*/{},
        /*res_attrs=*/{});
}

void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
                            mlir::StringAttr intrin, mlir::ValueRange args,
                            mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
  build(builder, state, /*resultTypes=*/TypeRange{}, intrin, args,
        fastMathFlags,
        /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{}, /*arg_attrs=*/{},
        /*res_attrs=*/{});
}

void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
                            mlir::Type resultType, mlir::StringAttr intrin,
                            mlir::ValueRange args) {
  build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
        /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{}, /*arg_attrs=*/{},
        /*res_attrs=*/{});
}

void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
                            mlir::TypeRange resultTypes,
                            mlir::StringAttr intrin, mlir::ValueRange args,
                            mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
  build(builder, state, resultTypes, intrin, args, fastMathFlags,
        /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{}, /*arg_attrs=*/{},
        /*res_attrs=*/{});
}

ParseResult CallIntrinsicOp::parse(OpAsmParser &parser,
                                   OperationState &result) {
  StringAttr intrinAttr;
  SmallVector<OpAsmParser::UnresolvedOperand, 4> operands;
  SmallVector<SmallVector<OpAsmParser::UnresolvedOperand>> opBundleOperands;
  SmallVector<SmallVector<Type>> opBundleOperandTypes;
  ArrayAttr opBundleTags;

  // Parse intrinsic name.
  if (parser.parseCustomAttributeWithFallback(
          intrinAttr, parser.getBuilder().getType<NoneType>()))
    return failure();
  result.addAttribute(CallIntrinsicOp::getIntrinAttrName(result.name),
                      intrinAttr);

  if (parser.parseLParen())
    return failure();

  // Parse the function arguments.
  if (parser.parseOperandList(operands))
    return mlir::failure();

  if (parser.parseRParen())
    return mlir::failure();

  // Handle bundles.
  SMLoc opBundlesLoc = parser.getCurrentLocation();
  if (std::optional<ParseResult> result = parseOpBundles(
          parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
      result && failed(*result))
    return failure();
  if (opBundleTags && !opBundleTags.empty())
    result.addAttribute(
        CallIntrinsicOp::getOpBundleTagsAttrName(result.name).getValue(),
        opBundleTags);

  if (parser.parseOptionalAttrDict(result.attributes))
    return mlir::failure();

  SmallVector<DictionaryAttr> argAttrs;
  SmallVector<DictionaryAttr> resultAttrs;
  if (parseCallTypeAndResolveOperands(parser, result, /*isDirect=*/true,
                                      operands, argAttrs, resultAttrs))
    return failure();
  call_interface_impl::addArgAndResultAttrs(
      parser.getBuilder(), result, argAttrs, resultAttrs,
      getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));

  if (resolveOpBundleOperands(parser, opBundlesLoc, result, opBundleOperands,
                              opBundleOperandTypes,
                              getOpBundleSizesAttrName(result.name)))
    return failure();

  int32_t numOpBundleOperands = 0;
  for (const auto &operands : opBundleOperands)
    numOpBundleOperands += operands.size();

  result.addAttribute(
      CallIntrinsicOp::getOperandSegmentSizeAttr(),
      parser.getBuilder().getDenseI32ArrayAttr(
          {static_cast<int32_t>(operands.size()), numOpBundleOperands}));

  return mlir::success();
}

void CallIntrinsicOp::print(OpAsmPrinter &p) {
  p << ' ';
  p.printAttributeWithoutType(getIntrinAttr());

  OperandRange args = getArgs();
  p << "(" << args << ")";

  // Operand bundles.
  if (!getOpBundleOperands().empty()) {
    p << ' ';
    printOpBundles(p, *this, getOpBundleOperands(),
                   getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
  }

  p.printOptionalAttrDict(processFMFAttr((*this)->getAttrs()),
                          {getOperandSegmentSizesAttrName(),
                           getOpBundleSizesAttrName(), getIntrinAttrName(),
                           getOpBundleTagsAttrName(), getArgAttrsAttrName(),
                           getResAttrsAttrName()});

  p << " : ";

  // Reconstruct the MLIR function type from operand and result types.
  call_interface_impl::printFunctionSignature(
      p, args.getTypes(), getArgAttrsAttr(),
      /*isVariadic=*/false, getResultTypes(), getResAttrsAttr());
}

//===----------------------------------------------------------------------===//
// LinkerOptionsOp
//===----------------------------------------------------------------------===//

LogicalResult LinkerOptionsOp::verify() {
  if (mlir::Operation *parentOp = (*this)->getParentOp();
      parentOp && !satisfiesLLVMModule(parentOp))
    return emitOpError("must appear at the module level");
  return success();
}

//===----------------------------------------------------------------------===//
// ModuleFlagsOp
//===----------------------------------------------------------------------===//

LogicalResult ModuleFlagsOp::verify() {
  if (Operation *parentOp = (*this)->getParentOp();
      parentOp && !satisfiesLLVMModule(parentOp))
    return emitOpError("must appear at the module level");

  llvm::DenseSet<StringAttr> seenNonRequireKeys;
  for (Attribute flag : getFlags()) {
    auto moduleFlag = dyn_cast<ModuleFlagAttrInterface>(flag);
    if (!moduleFlag)
      return emitOpError("expected a module flag attribute");
    if (failed(LLVM::detail::verifyModuleFlagValue(
            moduleFlag.getModuleFlagKey(), moduleFlag.getModuleFlagValue(),
            [&] { return emitOpError(); })))
      return failure();
    if (moduleFlag.getModuleFlagBehavior() == ModFlagBehavior::Require)
      continue;
    StringAttr key = moduleFlag.getModuleFlagKey();
    if (!seenNonRequireKeys.insert(key).second)
      return emitOpError("expected module flag key '")
             << key.getValue() << "' to be unique for non-require flags";
  }
  return success();
}

//===----------------------------------------------------------------------===//
// InlineAsmOp
//===----------------------------------------------------------------------===//

void InlineAsmOp::getEffects(
    SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
        &effects) {
  if (getHasSideEffects()) {
    effects.emplace_back(MemoryEffects::Write::get());
    effects.emplace_back(MemoryEffects::Read::get());
  }
}

//===----------------------------------------------------------------------===//
// BlockAddressOp
//===----------------------------------------------------------------------===//

LogicalResult
BlockAddressOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
  Operation *symbol = symbolTable.lookupSymbolIn(parentLLVMModule(*this),
                                                 getBlockAddr().getFunction());
  auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);

  if (!function)
    return emitOpError("must reference a function defined by 'llvm.func'");

  return success();
}

LLVMFuncOp BlockAddressOp::getFunction(SymbolTableCollection &symbolTable) {
  return dyn_cast_or_null<LLVMFuncOp>(symbolTable.lookupSymbolIn(
      parentLLVMModule(*this), getBlockAddr().getFunction()));
}

BlockTagOp BlockAddressOp::getBlockTagOp() {
  Operation *sym = mlir::SymbolTable::lookupNearestSymbolFrom(
      parentLLVMModule(*this), getBlockAddr().getFunction());
  if (!sym)
    return nullptr;
  auto funcOp = dyn_cast<LLVMFuncOp>(sym);
  if (!funcOp)
    return nullptr;
  BlockTagOp blockTagOp = nullptr;
  funcOp.walk([&](LLVM::BlockTagOp labelOp) {
    if (labelOp.getTag() == getBlockAddr().getTag()) {
      blockTagOp = labelOp;
      return WalkResult::interrupt();
    }
    return WalkResult::advance();
  });
  return blockTagOp;
}

LogicalResult BlockAddressOp::verify() {
  if (!getBlockTagOp())
    return emitOpError(
        "expects an existing block label target in the referenced function");

  return success();
}

/// Fold a blockaddress operation to a dedicated blockaddress
/// attribute.
OpFoldResult BlockAddressOp::fold(FoldAdaptor) { return getBlockAddr(); }

//===----------------------------------------------------------------------===//
// LLVM::IndirectBrOp
//===----------------------------------------------------------------------===//

SuccessorOperands IndirectBrOp::getSuccessorOperands(unsigned index) {
  assert(index < getNumSuccessors() && "invalid successor index");
  return SuccessorOperands(getSuccOperandsMutable()[index]);
}

void IndirectBrOp::build(OpBuilder &odsBuilder, OperationState &odsState,
                         Value addr, ArrayRef<ValueRange> succOperands,
                         BlockRange successors) {
  odsState.addOperands(addr);
  for (ValueRange range : succOperands)
    odsState.addOperands(range);
  SmallVector<int32_t> rangeSegments;
  for (ValueRange range : succOperands)
    rangeSegments.push_back(range.size());
  odsState.getOrAddProperties<Properties>().indbr_operand_segments =
      odsBuilder.getDenseI32ArrayAttr(rangeSegments);
  odsState.addSuccessors(successors);
}

static ParseResult parseIndirectBrOpSucessors(
    OpAsmParser &parser, Type &flagType,
    SmallVectorImpl<Block *> &succOperandBlocks,
    SmallVectorImpl<SmallVector<OpAsmParser::UnresolvedOperand>> &succOperands,
    SmallVectorImpl<SmallVector<Type>> &succOperandsTypes) {
  if (failed(parser.parseCommaSeparatedList(
          OpAsmParser::Delimiter::Square,
          [&]() {
            Block *destination = nullptr;
            SmallVector<OpAsmParser::UnresolvedOperand> operands;
            SmallVector<Type> operandTypes;

            if (parser.parseSuccessor(destination).failed())
              return failure();

            if (succeeded(parser.parseOptionalLParen())) {
              if (failed(parser.parseOperandList(
                      operands, OpAsmParser::Delimiter::None)) ||
                  failed(parser.parseColonTypeList(operandTypes)) ||
                  failed(parser.parseRParen()))
                return failure();
            }
            succOperandBlocks.push_back(destination);
            succOperands.emplace_back(operands);
            succOperandsTypes.emplace_back(operandTypes);
            return success();
          },
          "successor blocks")))
    return failure();
  return success();
}

static void
printIndirectBrOpSucessors(OpAsmPrinter &p, IndirectBrOp op, Type flagType,
                           SuccessorRange succs, OperandRangeRange succOperands,
                           const TypeRangeRange &succOperandsTypes) {
  p << "[";
  llvm::interleave(
      llvm::zip(succs, succOperands),
      [&](auto i) {
        p.printNewline();
        p.printSuccessorAndUseList(std::get<0>(i), std::get<1>(i));
      },
      [&] { p << ','; });
  if (!succOperands.empty())
    p.printNewline();
  p << "]";
}

//===----------------------------------------------------------------------===//
// SincosOp (intrinsic)
//===----------------------------------------------------------------------===//

LogicalResult LLVM::SincosOp::verify() {
  auto operandType = getOperand().getType();
  auto resultType = getResult().getType();
  auto resultStructType =
      mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
  if (!resultStructType || resultStructType.getBody().size() != 2 ||
      resultStructType.getBody()[0] != operandType ||
      resultStructType.getBody()[1] != operandType) {
    return emitOpError("expected result type to be an homogeneous struct with "
                       "two elements matching the operand type, but got ")
           << resultType;
  }
  return success();
}

//===----------------------------------------------------------------------===//
// AssumeOp (intrinsic)
//===----------------------------------------------------------------------===//

void LLVM::AssumeOp::build(OpBuilder &builder, OperationState &state,
                           mlir::Value cond) {
  return build(builder, state, cond, /*op_bundle_operands=*/{},
               /*op_bundle_tags=*/ArrayAttr{});
}

void LLVM::AssumeOp::build(OpBuilder &builder, OperationState &state,
                           Value cond, llvm::StringRef tag, ValueRange args) {
  return build(builder, state, cond, ArrayRef<ValueRange>(args),
               builder.getStrArrayAttr(tag));
}

void LLVM::AssumeOp::build(OpBuilder &builder, OperationState &state,
                           Value cond, AssumeAlignTag, Value ptr, Value align) {
  return build(builder, state, cond, "align", ValueRange{ptr, align});
}

void LLVM::AssumeOp::build(OpBuilder &builder, OperationState &state,
                           Value cond, AssumeSeparateStorageTag, Value ptr1,
                           Value ptr2) {
  return build(builder, state, cond, "separate_storage",
               ValueRange{ptr1, ptr2});
}

LogicalResult LLVM::AssumeOp::verify() { return verifyOperandBundles(*this); }

//===----------------------------------------------------------------------===//
// masked_gather (intrinsic)
//===----------------------------------------------------------------------===//

LogicalResult LLVM::masked_gather::verify() {
  auto ptrsVectorType = getPtrs().getType();
  Type expectedPtrsVectorType =
      LLVM::getVectorType(extractVectorElementType(ptrsVectorType),
                          LLVM::getVectorNumElements(getRes().getType()));
  // Vector of pointers type should match result vector type, other than the
  // element type.
  if (ptrsVectorType != expectedPtrsVectorType)
    return emitOpError("expected operand #1 type to be ")
           << expectedPtrsVectorType;
  return success();
}

//===----------------------------------------------------------------------===//
// masked_scatter (intrinsic)
//===----------------------------------------------------------------------===//

LogicalResult LLVM::masked_scatter::verify() {
  auto ptrsVectorType = getPtrs().getType();
  Type expectedPtrsVectorType =
      LLVM::getVectorType(extractVectorElementType(ptrsVectorType),
                          LLVM::getVectorNumElements(getValue().getType()));
  // Vector of pointers type should match value vector type, other than the
  // element type.
  if (ptrsVectorType != expectedPtrsVectorType)
    return emitOpError("expected operand #2 type to be ")
           << expectedPtrsVectorType;
  return success();
}

//===----------------------------------------------------------------------===//
// masked_expandload (intrinsic)
//===----------------------------------------------------------------------===//

void LLVM::masked_expandload::build(OpBuilder &builder, OperationState &state,
                                    mlir::TypeRange resTys, Value ptr,
                                    Value mask, Value passthru,
                                    uint64_t align) {
  ArrayAttr argAttrs = getLLVMAlignParamForCompressExpand(builder, true, align);
  build(builder, state, resTys, ptr, mask, passthru, /*arg_attrs=*/argAttrs,
        /*res_attrs=*/nullptr);
}

//===----------------------------------------------------------------------===//
// masked_compressstore (intrinsic)
//===----------------------------------------------------------------------===//

void LLVM::masked_compressstore::build(OpBuilder &builder,
                                       OperationState &state, Value value,
                                       Value ptr, Value mask, uint64_t align) {
  ArrayAttr argAttrs =
      getLLVMAlignParamForCompressExpand(builder, false, align);
  build(builder, state, value, ptr, mask, /*arg_attrs=*/argAttrs,
        /*res_attrs=*/nullptr);
}

//===----------------------------------------------------------------------===//
// InlineAsmOp
//===----------------------------------------------------------------------===//

LogicalResult InlineAsmOp::verify() {
  if (!getTailCallKindAttr())
    return success();

  if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
    return emitOpError(
        "tail call kind 'musttail' is not supported by this operation");

  return success();
}

//===----------------------------------------------------------------------===//
// UDivOp
//===----------------------------------------------------------------------===//
Speculation::Speculatability UDivOp::getSpeculatability() {
  // X / 0 => UB
  Value divisor = getRhs();
  if (matchPattern(divisor, m_IntRangeWithoutZeroU()))
    return Speculation::Speculatable;

  return Speculation::NotSpeculatable;
}

//===----------------------------------------------------------------------===//
// SDivOp
//===----------------------------------------------------------------------===//
Speculation::Speculatability SDivOp::getSpeculatability() {
  // This function conservatively assumes that all signed division by -1 are
  // not speculatable.
  // X / 0 => UB
  // INT_MIN / -1 => UB
  Value divisor = getRhs();
  if (matchPattern(divisor, m_IntRangeWithoutZeroS()) &&
      matchPattern(divisor, m_IntRangeWithoutNegOneS()))
    return Speculation::Speculatable;

  return Speculation::NotSpeculatable;
}

//===----------------------------------------------------------------------===//
// LLVMDialect initialization, type parsing, and registration.
//===----------------------------------------------------------------------===//

void LLVMDialect::initialize() {
  registerAttributes();

  // clang-format off
  addTypes<LLVMVoidType,
           LLVMLabelType,
           LLVMMetadataType>();
  // clang-format on
  registerTypes();

  addOperations<
#define GET_OP_LIST
#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"

      ,
#define GET_OP_LIST
#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"

      >();

  // Support unknown operations because not all LLVM operations are registered.
  allowUnknownOperations();
  declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
  detail::addBytecodeInterface(this);
}

#define GET_OP_CLASSES
#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"

#define GET_OP_CLASSES
#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"

LogicalResult LLVMDialect::verifyDataLayoutString(
    StringRef descr, llvm::function_ref<void(const Twine &)> reportError) {
  llvm::Expected<llvm::DataLayout> maybeDataLayout =
      llvm::DataLayout::parse(descr);
  if (maybeDataLayout)
    return success();

  std::string message;
  llvm::raw_string_ostream messageStream(message);
  llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
  reportError("invalid data layout descriptor: " + message);
  return failure();
}

/// Verify LLVM dialect attributes.
LogicalResult LLVMDialect::verifyOperationAttribute(Operation *op,
                                                    NamedAttribute attr) {
  // If the data layout attribute is present, it must use the LLVM data layout
  // syntax. Try parsing it and report errors in case of failure. Users of this
  // attribute may assume it is well-formed and can pass it to the (asserting)
  // llvm::DataLayout constructor.
  if (attr.getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
    return success();
  if (auto stringAttr = llvm::dyn_cast<StringAttr>(attr.getValue()))
    return verifyDataLayoutString(
        stringAttr.getValue(),
        [op](const Twine &message) { op->emitOpError() << message.str(); });

  return op->emitOpError() << "expected '"
                           << LLVM::LLVMDialect::getDataLayoutAttrName()
                           << "' to be a string attributes";
}

LogicalResult LLVMDialect::verifyParameterAttribute(Operation *op,
                                                    Type paramType,
                                                    NamedAttribute paramAttr) {
  // LLVM attribute may be attached to a result of operation that has not been
  // converted to LLVM dialect yet, so the result may have a type with unknown
  // representation in LLVM dialect type space. In this case we cannot verify
  // whether the attribute may be
  bool verifyValueType = isCompatibleType(paramType);
  StringAttr name = paramAttr.getName();

  auto checkUnitAttrType = [&]() -> LogicalResult {
    if (!llvm::isa<UnitAttr>(paramAttr.getValue()))
      return op->emitError() << name << " should be a unit attribute";
    return success();
  };
  auto checkTypeAttrType = [&]() -> LogicalResult {
    if (!llvm::isa<TypeAttr>(paramAttr.getValue()))
      return op->emitError() << name << " should be a type attribute";
    return success();
  };
  auto checkIntegerAttrType = [&]() -> LogicalResult {
    if (!llvm::isa<IntegerAttr>(paramAttr.getValue()))
      return op->emitError() << name << " should be an integer attribute";
    return success();
  };
  auto checkPointerType = [&]() -> LogicalResult {
    if (!llvm::isa<LLVMPointerType>(paramType))
      return op->emitError()
             << name << " attribute attached to non-pointer LLVM type";
    return success();
  };
  auto checkIntegerType = [&]() -> LogicalResult {
    if (!llvm::isa<IntegerType>(paramType))
      return op->emitError()
             << name << " attribute attached to non-integer LLVM type";
    return success();
  };
  auto checkPointerTypeMatches = [&]() -> LogicalResult {
    if (failed(checkPointerType()))
      return failure();

    return success();
  };

  // Check a unit attribute that is attached to a pointer value.
  if (name == LLVMDialect::getNoAliasAttrName() ||
      name == LLVMDialect::getReadonlyAttrName() ||
      name == LLVMDialect::getReadnoneAttrName() ||
      name == LLVMDialect::getWriteOnlyAttrName() ||
      name == LLVMDialect::getNestAttrName() ||
      name == LLVMDialect::getNoCaptureAttrName() ||
      name == LLVMDialect::getNoFreeAttrName() ||
      name == LLVMDialect::getNonNullAttrName()) {
    if (failed(checkUnitAttrType()))
      return failure();
    if (verifyValueType && failed(checkPointerType()))
      return failure();
    return success();
  }

  // Check a type attribute that is attached to a pointer value.
  if (name == LLVMDialect::getStructRetAttrName() ||
      name == LLVMDialect::getByValAttrName() ||
      name == LLVMDialect::getByRefAttrName() ||
      name == LLVMDialect::getElementTypeAttrName() ||
      name == LLVMDialect::getInAllocaAttrName() ||
      name == LLVMDialect::getPreallocatedAttrName()) {
    if (failed(checkTypeAttrType()))
      return failure();
    if (verifyValueType && failed(checkPointerTypeMatches()))
      return failure();
    return success();
  }

  // Check a unit attribute that is attached to an integer value.
  if (name == LLVMDialect::getSExtAttrName() ||
      name == LLVMDialect::getZExtAttrName()) {
    if (failed(checkUnitAttrType()))
      return failure();
    if (verifyValueType && failed(checkIntegerType()))
      return failure();
    return success();
  }

  // Check an integer attribute that is attached to a pointer value.
  if (name == LLVMDialect::getAlignAttrName() ||
      name == LLVMDialect::getDereferenceableAttrName() ||
      name == LLVMDialect::getDereferenceableOrNullAttrName()) {
    if (failed(checkIntegerAttrType()))
      return failure();
    if (verifyValueType && failed(checkPointerType()))
      return failure();
    return success();
  }

  // Check an integer attribute that is attached to a pointer value.
  if (name == LLVMDialect::getStackAlignmentAttrName()) {
    if (failed(checkIntegerAttrType()))
      return failure();
    return success();
  }

  // Check a unit attribute that can be attached to arbitrary types.
  if (name == LLVMDialect::getNoUndefAttrName() ||
      name == LLVMDialect::getInRegAttrName() ||
      name == LLVMDialect::getReturnedAttrName())
    return checkUnitAttrType();

  return success();
}

/// Verify LLVMIR function argument attributes.
LogicalResult LLVMDialect::verifyRegionArgAttribute(Operation *op,
                                                    unsigned regionIdx,
                                                    unsigned argIdx,
                                                    NamedAttribute argAttr) {
  auto funcOp = dyn_cast<FunctionOpInterface>(op);
  if (!funcOp)
    return success();
  Type argType = funcOp.getArgumentTypes()[argIdx];

  return verifyParameterAttribute(op, argType, argAttr);
}

LogicalResult LLVMDialect::verifyRegionResultAttribute(Operation *op,
                                                       unsigned regionIdx,
                                                       unsigned resIdx,
                                                       NamedAttribute resAttr) {
  auto funcOp = dyn_cast<FunctionOpInterface>(op);
  if (!funcOp)
    return success();
  Type resType = funcOp.getResultTypes()[resIdx];

  // Check to see if this function has a void return with a result attribute
  // to it. It isn't clear what semantics we would assign to that.
  if (llvm::isa<LLVMVoidType>(resType))
    return op->emitError() << "cannot attach result attributes to functions "
                              "with a void return";

  // Check to see if this attribute is allowed as a result attribute. Only
  // explicitly forbidden LLVM attributes will cause an error.
  auto name = resAttr.getName();
  if (name == LLVMDialect::getAllocAlignAttrName() ||
      name == LLVMDialect::getAllocatedPointerAttrName() ||
      name == LLVMDialect::getByValAttrName() ||
      name == LLVMDialect::getByRefAttrName() ||
      name == LLVMDialect::getInAllocaAttrName() ||
      name == LLVMDialect::getNestAttrName() ||
      name == LLVMDialect::getNoCaptureAttrName() ||
      name == LLVMDialect::getNoFreeAttrName() ||
      name == LLVMDialect::getPreallocatedAttrName() ||
      name == LLVMDialect::getReadnoneAttrName() ||
      name == LLVMDialect::getReadonlyAttrName() ||
      name == LLVMDialect::getReturnedAttrName() ||
      name == LLVMDialect::getStackAlignmentAttrName() ||
      name == LLVMDialect::getStructRetAttrName() ||
      name == LLVMDialect::getWriteOnlyAttrName())
    return op->emitError() << name << " is not a valid result attribute";
  return verifyParameterAttribute(op, resType, resAttr);
}

Operation *LLVMDialect::materializeConstant(OpBuilder &builder, Attribute value,
                                            Type type, Location loc) {
  // If this was folded from an operation other than llvm.mlir.constant, it
  // should be materialized as such. Note that an llvm.mlir.zero may fold into
  // a builtin zero attribute and thus will materialize as a llvm.mlir.constant.
  if (auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
    if (isa<LLVM::LLVMPointerType>(type))
      return LLVM::AddressOfOp::create(builder, loc, type, symbol);
  if (isa<LLVM::UndefAttr>(value))
    return LLVM::UndefOp::create(builder, loc, type);
  if (isa<LLVM::PoisonAttr>(value))
    return LLVM::PoisonOp::create(builder, loc, type);
  if (isa<LLVM::ZeroAttr>(value))
    return LLVM::ZeroOp::create(builder, loc, type);
  if (isa<LLVM::MDStringAttr, LLVM::MDConstantAttr, LLVM::MDGlobalValueAttr,
          LLVM::MDNodeAttr>(value))
    if (isa<LLVM::LLVMMetadataType>(type))
      return LLVM::MetadataAsValueOp::create(builder, loc, type, value);
  // Otherwise try materializing it as a regular llvm.mlir.constant op.
  return LLVM::ConstantOp::materialize(builder, value, type, loc);
}

//===----------------------------------------------------------------------===//
// Utility functions.
//===----------------------------------------------------------------------===//

Value mlir::LLVM::createGlobalString(Location loc, OpBuilder &builder,
                                     StringRef name, StringRef value,
                                     LLVM::Linkage linkage) {
  assert(builder.getInsertionBlock() &&
         builder.getInsertionBlock()->getParentOp() &&
         "expected builder to point to a block constrained in an op");
  auto module =
      builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
  assert(module && "builder points to an op outside of a module");

  // Create the global at the entry of the module.
  OpBuilder moduleBuilder(module.getBodyRegion(), builder.getListener());
  MLIRContext *ctx = builder.getContext();
  auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
  auto global = LLVM::GlobalOp::create(
      moduleBuilder, loc, type, /*isConstant=*/true, linkage, name,
      builder.getStringAttr(value), /*alignment=*/0);

  LLVMPointerType ptrType = LLVMPointerType::get(ctx);
  // Get the pointer to the first character in the global string.
  Value globalPtr =
      LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
  return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
                             ArrayRef<GEPArg>{0, 0});
}

bool mlir::LLVM::satisfiesLLVMModule(Operation *op) {
  return op->hasTrait<OpTrait::SymbolTable>() &&
         op->hasTrait<OpTrait::IsIsolatedFromAbove>();
}

Operation *mlir::LLVM::parentLLVMModule(Operation *op) {
  Operation *module = op->getParentOp();
  while (module && !satisfiesLLVMModule(module))
    module = module->getParentOp();
  assert(module && "unexpected operation outside of a module");
  return module;
}
