15#include "mlir/IR/DialectImplementation.h"
19#include "llvm/ADT/TypeSwitch.h"
25 if (
auto sizedTy = mlir::dyn_cast<cir::SizedTypeInterface>(ty))
26 return sizedTy.isSized();
35static mlir::ParseResult
39 mlir::ArrayRef<mlir::Type> params,
48#include "clang/CIR/Dialect/IR/CIRTypeConstraints.cpp.inc"
52#define GET_TYPEDEF_CLASSES
53#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
62Type CIRDialect::parseType(DialectAsmParser &parser)
const {
63 llvm::SMLoc typeLoc = parser.getCurrentLocation();
64 llvm::StringRef mnemonic;
68 OptionalParseResult parseResult =
69 generatedTypeParser(parser, &mnemonic, genType);
70 if (parseResult.has_value())
74 return StringSwitch<function_ref<Type()>>(mnemonic)
75 .Case(
"record", [&] {
return RecordType::parse(parser); })
77 parser.emitError(typeLoc) <<
"unknown CIR type: " << mnemonic;
82void CIRDialect::printType(Type type, DialectAsmPrinter &os)
const {
84 if (generatedTypePrinter(type, os).succeeded())
88 llvm::report_fatal_error(
"printer is missing a handler for this type");
95Type RecordType::parse(mlir::AsmParser &parser) {
96 FailureOr<AsmParser::CyclicParseReset> cyclicParseGuard;
97 const llvm::SMLoc loc = parser.getCurrentLocation();
98 const mlir::Location eLoc = parser.getEncodedSourceLoc(loc);
102 mlir::MLIRContext *context = parser.getContext();
104 if (parser.parseLess())
109 if (parser.parseOptionalKeyword(
"struct").succeeded())
110 kind = RecordKind::Struct;
111 else if (parser.parseOptionalKeyword(
"union").succeeded())
112 kind = RecordKind::Union;
113 else if (parser.parseOptionalKeyword(
"class").succeeded())
114 kind = RecordKind::Class;
116 parser.emitError(loc,
"unknown record type");
120 mlir::StringAttr
name;
121 parser.parseOptionalAttribute(name);
124 if (name && parser.parseOptionalGreater().succeeded()) {
125 RecordType
type = getChecked(eLoc, context, name, kind);
126 if (succeeded(parser.tryStartCyclicParse(type))) {
127 parser.emitError(loc,
"invalid self-reference within record");
135 RecordType
type = getChecked(eLoc, context, name, kind);
136 cyclicParseGuard = parser.tryStartCyclicParse(type);
137 if (failed(cyclicParseGuard)) {
138 parser.emitError(loc,
"record already defined");
143 if (parser.parseOptionalKeyword(
"packed").succeeded())
146 if (parser.parseOptionalKeyword(
"padded").succeeded())
150 bool incomplete =
true;
151 llvm::SmallVector<mlir::Type> members;
152 if (parser.parseOptionalKeyword(
"incomplete").failed()) {
154 const auto delimiter = AsmParser::Delimiter::Braces;
155 const auto parseElementFn = [&parser, &members]() {
156 return parser.parseType(members.emplace_back());
158 if (parser.parseCommaSeparatedList(delimiter, parseElementFn).failed())
162 if (parser.parseGreater())
166 ArrayRef<mlir::Type> membersRef(members);
167 mlir::Type
type = {};
168 if (name && incomplete) {
169 type = getChecked(eLoc, context, name, kind);
170 }
else if (!name && !incomplete) {
171 type = getChecked(eLoc, context, membersRef, packed, padded, kind);
172 }
else if (!incomplete) {
173 type = getChecked(eLoc, context, membersRef, name, packed, padded, kind);
176 if (mlir::cast<RecordType>(type).isIncomplete())
177 mlir::cast<RecordType>(type).complete(membersRef, packed, padded);
180 parser.emitError(loc,
"anonymous records must be complete");
187void RecordType::print(mlir::AsmPrinter &printer)
const {
188 FailureOr<AsmPrinter::CyclicPrintReset> cyclicPrintGuard;
192 case RecordKind::Struct:
193 printer <<
"struct ";
195 case RecordKind::Union:
198 case RecordKind::Class:
207 cyclicPrintGuard = printer.tryStartCyclicPrint(*
this);
208 if (failed(cyclicPrintGuard)) {
217 printer <<
"packed ";
220 printer <<
"padded ";
222 if (isIncomplete()) {
223 printer <<
"incomplete";
226 llvm::interleaveComma(getMembers(), printer);
234RecordType::verify(function_ref<mlir::InFlightDiagnostic()> emitError,
235 llvm::ArrayRef<mlir::Type> members, mlir::StringAttr name,
236 bool incomplete,
bool packed,
bool padded,
237 RecordType::RecordKind kind) {
238 if (name &&
name.getValue().empty())
239 return emitError() <<
"identified records cannot have an empty name";
240 return mlir::success();
243::llvm::ArrayRef<mlir::Type> RecordType::getMembers()
const {
247bool RecordType::isIncomplete()
const {
return getImpl()->incomplete; }
249mlir::StringAttr RecordType::getName()
const {
return getImpl()->name; }
251bool RecordType::getIncomplete()
const {
return getImpl()->incomplete; }
253bool RecordType::getPacked()
const {
return getImpl()->packed; }
255bool RecordType::getPadded()
const {
return getImpl()->padded; }
257cir::RecordType::RecordKind RecordType::getKind()
const {
261void RecordType::complete(ArrayRef<Type> members,
bool packed,
bool padded) {
263 if (mutate(members, packed, padded).failed())
264 llvm_unreachable(
"failed to complete record");
270Type RecordType::getLargestMember(const ::mlir::DataLayout &dataLayout)
const {
271 assert(isUnion() &&
"Only call getLargestMember on unions");
272 llvm::ArrayRef<Type> members = getMembers();
275 return *std::max_element(
276 members.begin(), getPadded() ? members.end() - 1 : members.end(),
277 [&](Type lhs, Type rhs) {
278 return dataLayout.getTypeABIAlignment(lhs) <
279 dataLayout.getTypeABIAlignment(rhs) ||
280 (dataLayout.getTypeABIAlignment(lhs) ==
281 dataLayout.getTypeABIAlignment(rhs) &&
282 dataLayout.getTypeSize(lhs) < dataLayout.getTypeSize(rhs));
286bool RecordType::isLayoutIdentical(
const RecordType &other) {
287 if (
getImpl() == other.getImpl())
290 if (getPacked() != other.getPacked())
293 return getMembers() == other.getMembers();
301RecordType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
302 mlir::DataLayoutEntryListRef params)
const {
304 return dataLayout.getTypeSize(getLargestMember(dataLayout));
306 unsigned recordSize = computeStructSize(dataLayout);
307 return llvm::TypeSize::getFixed(recordSize * 8);
311RecordType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
312 ::mlir::DataLayoutEntryListRef params)
const {
314 return dataLayout.getTypeABIAlignment(getLargestMember(dataLayout));
319 return computeStructAlignment(dataLayout);
323RecordType::computeStructSize(
const mlir::DataLayout &dataLayout)
const {
324 assert(isComplete() &&
"Cannot get layout of incomplete records");
327 unsigned recordSize = 0;
330 for (mlir::Type ty : getMembers()) {
334 (getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
338 recordSize = llvm::alignTo(recordSize, tyAlign);
339 recordSize += dataLayout.getTypeSize(ty);
343 recordAlignment = std::max(tyAlign, recordAlignment);
348 recordSize = llvm::alignTo(recordSize, recordAlignment);
357RecordType::computeStructAlignment(
const mlir::DataLayout &dataLayout)
const {
358 assert(isComplete() &&
"Cannot get layout of incomplete records");
362 for (mlir::Type ty : getMembers())
364 std::max(dataLayout.getTypeABIAlignment(ty), recordAlignment);
366 return recordAlignment;
369uint64_t RecordType::getElementOffset(const ::mlir::DataLayout &dataLayout,
370 unsigned idx)
const {
371 assert(idx < getMembers().size() &&
"access not valid");
374 if (isUnion() || idx == 0)
377 assert(isComplete() &&
"Cannot get layout of incomplete records");
378 assert(idx < getNumElements());
379 llvm::ArrayRef<mlir::Type> members = getMembers();
384 llvm::make_range(members.begin(), std::next(members.begin(), idx))) {
386 const llvm::Align tyAlign =
387 llvm::Align(getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
390 offset = llvm::alignTo(offset, tyAlign);
393 offset += dataLayout.getTypeSize(ty);
398 const llvm::Align tyAlign = llvm::Align(
399 getPacked() ? 1 : dataLayout.getTypeABIAlignment(members[idx]));
400 offset = llvm::alignTo(offset, tyAlign);
409Type IntType::parse(mlir::AsmParser &parser) {
410 mlir::MLIRContext *context = parser.getBuilder().getContext();
411 llvm::SMLoc loc = parser.getCurrentLocation();
415 if (parser.parseLess())
419 llvm::StringRef
sign;
420 if (parser.parseKeyword(&
sign))
424 else if (
sign ==
"u")
427 parser.emitError(loc,
"expected 's' or 'u'");
431 if (parser.parseComma())
435 if (parser.parseInteger(width))
437 if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
438 parser.emitError(loc,
"expected integer width to be from ")
439 << IntType::minBitwidth() <<
" up to " << IntType::maxBitwidth();
443 if (parser.parseGreater())
446 return IntType::get(context, width, isSigned);
449void IntType::print(mlir::AsmPrinter &printer)
const {
450 char sign = isSigned() ?
's' :
'u';
451 printer <<
'<' <<
sign <<
", " << getWidth() <<
'>';
455IntType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
456 mlir::DataLayoutEntryListRef params)
const {
457 return llvm::TypeSize::getFixed(getWidth());
460uint64_t IntType::getABIAlignment(
const mlir::DataLayout &dataLayout,
461 mlir::DataLayoutEntryListRef params)
const {
462 return (uint64_t)(getWidth() / 8);
466IntType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
467 unsigned width,
bool isSigned) {
468 if (width < IntType::minBitwidth() || width > IntType::maxBitwidth())
469 return emitError() <<
"IntType only supports widths from "
470 << IntType::minBitwidth() <<
" up to "
471 << IntType::maxBitwidth();
472 return mlir::success();
476 return width == 8 || width == 16 || width == 32 || width == 64;
483const llvm::fltSemantics &SingleType::getFloatSemantics()
const {
484 return llvm::APFloat::IEEEsingle();
488SingleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
489 mlir::DataLayoutEntryListRef params)
const {
490 return llvm::TypeSize::getFixed(getWidth());
494SingleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
495 mlir::DataLayoutEntryListRef params)
const {
496 return (uint64_t)(getWidth() / 8);
499const llvm::fltSemantics &DoubleType::getFloatSemantics()
const {
500 return llvm::APFloat::IEEEdouble();
504DoubleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
505 mlir::DataLayoutEntryListRef params)
const {
506 return llvm::TypeSize::getFixed(getWidth());
510DoubleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
511 mlir::DataLayoutEntryListRef params)
const {
512 return (uint64_t)(getWidth() / 8);
515const llvm::fltSemantics &FP16Type::getFloatSemantics()
const {
516 return llvm::APFloat::IEEEhalf();
520FP16Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
521 mlir::DataLayoutEntryListRef params)
const {
522 return llvm::TypeSize::getFixed(getWidth());
525uint64_t FP16Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
526 mlir::DataLayoutEntryListRef params)
const {
527 return (uint64_t)(getWidth() / 8);
530const llvm::fltSemantics &BF16Type::getFloatSemantics()
const {
531 return llvm::APFloat::BFloat();
535BF16Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
536 mlir::DataLayoutEntryListRef params)
const {
537 return llvm::TypeSize::getFixed(getWidth());
540uint64_t BF16Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
541 mlir::DataLayoutEntryListRef params)
const {
542 return (uint64_t)(getWidth() / 8);
545const llvm::fltSemantics &FP80Type::getFloatSemantics()
const {
546 return llvm::APFloat::x87DoubleExtended();
550FP80Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
551 mlir::DataLayoutEntryListRef params)
const {
553 return llvm::TypeSize::getFixed(128);
556uint64_t FP80Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
557 mlir::DataLayoutEntryListRef params)
const {
561const llvm::fltSemantics &FP128Type::getFloatSemantics()
const {
562 return llvm::APFloat::IEEEquad();
566FP128Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
567 mlir::DataLayoutEntryListRef params)
const {
568 return llvm::TypeSize::getFixed(getWidth());
571uint64_t FP128Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
572 mlir::DataLayoutEntryListRef params)
const {
576const llvm::fltSemantics &LongDoubleType::getFloatSemantics()
const {
577 return mlir::cast<cir::FPTypeInterface>(getUnderlying()).getFloatSemantics();
581LongDoubleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
582 mlir::DataLayoutEntryListRef params)
const {
583 return mlir::cast<mlir::DataLayoutTypeInterface>(getUnderlying())
584 .getTypeSizeInBits(dataLayout, params);
588LongDoubleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
589 mlir::DataLayoutEntryListRef params)
const {
590 return mlir::cast<mlir::DataLayoutTypeInterface>(getUnderlying())
591 .getABIAlignment(dataLayout, params);
599cir::ComplexType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
600 mlir::DataLayoutEntryListRef params)
const {
606 return dataLayout.getTypeSizeInBits(getElementType()) * 2;
610cir::ComplexType::getABIAlignment(
const mlir::DataLayout &dataLayout,
611 mlir::DataLayoutEntryListRef params)
const {
617 return dataLayout.getTypeABIAlignment(getElementType());
620FuncType FuncType::clone(TypeRange inputs, TypeRange results)
const {
621 assert(results.size() == 1 &&
"expected exactly one result type");
622 return get(llvm::to_vector(inputs), results[0], isVarArg());
626static mlir::ParseResult
630 return p.parseCommaSeparatedList(
631 AsmParser::Delimiter::Paren, [&]() -> mlir::ParseResult {
633 return p.emitError(p.getCurrentLocation(),
634 "variadic `...` must be the last parameter");
635 if (succeeded(p.parseOptionalEllipsis())) {
640 if (failed(p.parseType(type)))
642 params.push_back(type);
648 mlir::ArrayRef<mlir::Type> params,
651 llvm::interleaveComma(params, p,
652 [&p](mlir::Type type) { p.printType(type); });
663mlir::Type FuncType::getReturnType()
const {
665 return cir::VoidType::get(getContext());
666 return getOptionalReturnType();
672llvm::ArrayRef<mlir::Type> FuncType::getReturnTypes()
const {
678 return getImpl()->optionalReturnType;
682bool FuncType::hasVoidReturn()
const {
return !getOptionalReturnType(); }
685FuncType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
686 llvm::ArrayRef<mlir::Type> argTypes, mlir::Type returnType,
688 if (mlir::isa_and_nonnull<cir::VoidType>(returnType))
690 <<
"!cir.func cannot have an explicit 'void' return type";
691 return mlir::success();
699BoolType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
700 ::mlir::DataLayoutEntryListRef params)
const {
701 return llvm::TypeSize::getFixed(8);
705BoolType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
706 ::mlir::DataLayoutEntryListRef params)
const {
715VPtrType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
716 mlir::DataLayoutEntryListRef params)
const {
718 return llvm::TypeSize::getFixed(64);
721uint64_t VPtrType::getABIAlignment(
const mlir::DataLayout &dataLayout,
722 mlir::DataLayoutEntryListRef params)
const {
732ArrayType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
733 ::mlir::DataLayoutEntryListRef params)
const {
734 return getSize() * dataLayout.getTypeSizeInBits(getElementType());
738ArrayType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
739 ::mlir::DataLayoutEntryListRef params)
const {
740 return dataLayout.getTypeABIAlignment(getElementType());
747llvm::TypeSize cir::VectorType::getTypeSizeInBits(
748 const ::mlir::DataLayout &dataLayout,
749 ::mlir::DataLayoutEntryListRef params)
const {
750 return llvm::TypeSize::getFixed(
751 getSize() * dataLayout.getTypeSizeInBits(getElementType()));
755cir::VectorType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
756 ::mlir::DataLayoutEntryListRef params)
const {
757 return llvm::NextPowerOf2(dataLayout.getTypeSizeInBits(*
this));
760mlir::LogicalResult cir::VectorType::verify(
761 llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
762 mlir::Type elementType, uint64_t size) {
764 return emitError() <<
"the number of vector elements must be non-zero";
773PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
774 ::mlir::DataLayoutEntryListRef params)
const {
776 return llvm::TypeSize::getFixed(64);
780PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
781 ::mlir::DataLayoutEntryListRef params)
const {
787PointerType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
788 mlir::Type pointee) {
790 return mlir::success();
797void CIRDialect::registerTypes() {
800#define GET_TYPEDEF_LIST
801#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
static mlir::ParseResult parseFuncTypeParams(mlir::AsmParser &p, llvm::SmallVector< mlir::Type > ¶ms, bool &isVarArg)
static void printFuncTypeParams(mlir::AsmPrinter &p, mlir::ArrayRef< mlir::Type > params, bool isVarArg)
static Decl::Kind getKind(const Decl *D)
static LiveVariablesImpl & getImpl(void *x)
bool isValidFundamentalIntWidth(unsigned width)
bool isSized(mlir::Type ty)
Returns true if the type is a CIR sized type.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
StringRef getName(const HeaderType T)
float __ovld __cnfn sign(float)
Returns 1.0 if x > 0, -0.0 if x = -0.0, +0.0 if x = +0.0, or -1.0 if x < 0.
static bool unsizedTypes()
static bool astRecordDeclAttr()