"FIR logical type">;
def fir_RealType : Type<CPred<"$_self.isa<fir::RealType>()">,
"FIR real type">;
+def fir_VectorType : Type<CPred<"$_self.isa<fir::VectorType>()">,
+ "FIR vector type">;
// Generalized FIR and standard dialect types representing intrinsic types
def AnyIntegerLike : TypeConstraint<Or<[SignlessIntegerLike.predicate,
// Composable types
def AnyCompositeLike : TypeConstraint<Or<[fir_RecordType.predicate,
fir_SequenceType.predicate, fir_ComplexType.predicate,
- IsTupleTypePred]>, "any composite">;
+ fir_VectorType.predicate, IsTupleTypePred]>, "any composite">;
// Reference to an entity type
def fir_ReferenceType : Type<CPred<"$_self.isa<fir::ReferenceType>()">,
struct ReferenceTypeStorage;
struct SequenceTypeStorage;
struct TypeDescTypeStorage;
+struct VectorTypeStorage;
} // namespace detail
// These isa_ routines follow the precedent of llvm::isa_or_null<>
llvm::StringRef name);
};
-mlir::Type parseFirType(FIROpsDialect *, mlir::DialectAsmParser &parser);
-
-void printFirType(FIROpsDialect *, mlir::Type ty, mlir::DialectAsmPrinter &p);
-
-/// Guarantee `type` is a scalar integral type (standard Integer, standard
-/// Index, or FIR Int). Aborts execution if condition is false.
-void verifyIntegralType(mlir::Type type);
-
/// Is `t` a FIR Real or MLIR Float type?
inline bool isa_real(mlir::Type t) {
return t.isa<fir::RealType>() || t.isa<mlir::FloatType>();
t.isa<fir::IntegerType>();
}
+/// Replacement for the builtin vector type.
+/// The FIR vector type is always rank one. It's size is always a constant.
+/// A vector's element type must be real or integer.
+class VectorType : public mlir::Type::TypeBase<fir::VectorType, mlir::Type,
+ detail::VectorTypeStorage> {
+public:
+ using Base::Base;
+
+ static fir::VectorType get(uint64_t len, mlir::Type eleTy);
+ mlir::Type getEleTy() const;
+ uint64_t getLen() const;
+
+ static mlir::LogicalResult
+ verifyConstructionInvariants(mlir::Location, uint64_t len, mlir::Type eleTy);
+ static bool isValidElementType(mlir::Type t) {
+ return isa_real(t) || isa_integer(t);
+ }
+};
+
+mlir::Type parseFirType(FIROpsDialect *, mlir::DialectAsmParser &parser);
+
+void printFirType(FIROpsDialect *, mlir::Type ty, mlir::DialectAsmPrinter &p);
+
+/// Guarantee `type` is a scalar integral type (standard Integer, standard
+/// Index, or FIR Int). Aborts execution if condition is false.
+void verifyIntegralType(mlir::Type type);
+
/// Is `t` a FIR or MLIR Complex type?
inline bool isa_complex(mlir::Type t) {
return t.isa<fir::ComplexType>() || t.isa<mlir::ComplexType>();
addTypes<BoxType, BoxCharType, BoxProcType, CharacterType, fir::ComplexType,
FieldType, HeapType, fir::IntegerType, LenType, LogicalType,
PointerType, RealType, RecordType, ReferenceType, SequenceType,
- TypeDescType>();
+ TypeDescType, fir::VectorType>();
addAttributes<ClosedIntervalAttr, ExactTypeAttr, LowerBoundAttr,
PointIntervalAttr, RealAttr, SubclassAttr, UpperBoundAttr>();
addOperations<
return parseTypeSingleton<TypeDescType>(parser, loc);
}
+// `vector` `<` len `:` type `>`
+fir::VectorType parseVector(mlir::DialectAsmParser &parser,
+ mlir::Location loc) {
+ int64_t len = 0;
+ mlir::Type eleTy;
+ if (parser.parseLess() || parser.parseInteger(len) || parser.parseColon() ||
+ parser.parseType(eleTy) || parser.parseGreater()) {
+ parser.emitError(parser.getNameLoc(), "invalid vector type");
+ return {};
+ }
+ return fir::VectorType::get(len, eleTy);
+}
+
// `void`
mlir::Type parseVoid(mlir::DialectAsmParser &parser) {
return parser.getBuilder().getNoneType();
return parseDerived(parser, loc);
if (typeNameLit == "void")
return parseVoid(parser);
+ if (typeNameLit == "vector")
+ return parseVector(parser, loc);
parser.emitError(parser.getNameLoc(), "unknown FIR type " + typeNameLit);
return {};
explicit TypeDescTypeStorage(mlir::Type ofTy) : ofTy{ofTy} {}
};
+/// Vector type storage
+struct VectorTypeStorage : public mlir::TypeStorage {
+ using KeyTy = std::tuple<uint64_t, mlir::Type>;
+
+ static unsigned hashKey(const KeyTy &key) {
+ return llvm::hash_combine(std::get<uint64_t>(key),
+ std::get<mlir::Type>(key));
+ }
+
+ bool operator==(const KeyTy &key) const {
+ return key == KeyTy{getLen(), getEleTy()};
+ }
+
+ static VectorTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
+ const KeyTy &key) {
+ auto *storage = allocator.allocate<VectorTypeStorage>();
+ return new (storage)
+ VectorTypeStorage{std::get<uint64_t>(key), std::get<mlir::Type>(key)};
+ }
+
+ uint64_t getLen() const { return len; }
+ mlir::Type getEleTy() const { return eleTy; }
+
+protected:
+ uint64_t len;
+ mlir::Type eleTy;
+
+private:
+ VectorTypeStorage() = delete;
+ explicit VectorTypeStorage(uint64_t len, mlir::Type eleTy)
+ : len{len}, eleTy{eleTy} {}
+};
+
} // namespace detail
template <typename A, typename B>
eleTy.isa<BoxProcType>() || eleTy.isa<FieldType>() ||
eleTy.isa<LenType>() || eleTy.isa<HeapType>() ||
eleTy.isa<PointerType>() || eleTy.isa<ReferenceType>() ||
- eleTy.isa<TypeDescType>() || eleTy.isa<SequenceType>())
+ eleTy.isa<TypeDescType>() || eleTy.isa<fir::VectorType>() ||
+ eleTy.isa<SequenceType>())
return mlir::emitError(loc, "cannot build an array of this element type: ")
<< eleTy << '\n';
return mlir::success();
}
+//===----------------------------------------------------------------------===//
+// Vector type
+//===----------------------------------------------------------------------===//
+
+fir::VectorType fir::VectorType::get(uint64_t len, mlir::Type eleTy) {
+ return Base::get(eleTy.getContext(), len, eleTy);
+}
+
+mlir::Type fir::VectorType::getEleTy() const { return getImpl()->getEleTy(); }
+
+uint64_t fir::VectorType::getLen() const { return getImpl()->getLen(); }
+
+mlir::LogicalResult
+fir::VectorType::verifyConstructionInvariants(mlir::Location loc, uint64_t len,
+ mlir::Type eleTy) {
+ if (!(fir::isa_real(eleTy) || fir::isa_integer(eleTy)))
+ return mlir::emitError(loc, "cannot build a vector of type ")
+ << eleTy << '\n';
+ return mlir::success();
+}
+
// compare if two shapes are equivalent
bool fir::operator==(const SequenceType::Shape &sh_1,
const SequenceType::Shape &sh_2) {
os << '>';
return;
}
+ if (auto type = ty.dyn_cast<fir::VectorType>()) {
+ os << "vector<" << type.getLen() << ':';
+ p.printType(type.getEleTy());
+ os << '>';
+ return;
+ }
}
// CHECK-LABEL: func private @oth3() -> !fir.tdesc<!fir.type<derived7{f1:f32,f2:f32}>>
func private @oth2() -> !fir.field
func private @oth3() -> !fir.tdesc<!fir.type<derived7{f1:f32,f2:f32}>>
+
+// FIR vector
+// CHECK-LABEL: func private @vecty(i1) -> !fir.vector<10:i32>
+func private @vecty(i1) -> !fir.vector<10:i32>