15#include "mlir/IR/DialectImplementation.h"
20#include "llvm/ADT/TypeSwitch.h"
26 if (
auto sizedTy = mlir::dyn_cast<cir::SizedTypeInterface>(ty))
27 return sizedTy.isSized();
36static mlir::ParseResult
40 mlir::ArrayRef<mlir::Type> params,
46static mlir::ParseResult
51 mlir::ArrayRef<mlir::Type> params,
59 cir::TargetAddressSpaceAttr &attr);
62 cir::TargetAddressSpaceAttr attr);
70#include "clang/CIR/Dialect/IR/CIRTypeConstraints.cpp.inc"
74#define GET_TYPEDEF_CLASSES
75#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
84Type CIRDialect::parseType(DialectAsmParser &parser)
const {
85 llvm::SMLoc typeLoc = parser.getCurrentLocation();
86 llvm::StringRef mnemonic;
90 OptionalParseResult parseResult =
91 generatedTypeParser(parser, &mnemonic, genType);
92 if (parseResult.has_value())
96 return StringSwitch<function_ref<Type()>>(mnemonic)
97 .Case(
"record", [&] {
return RecordType::parse(parser); })
99 parser.emitError(typeLoc) <<
"unknown CIR type: " << mnemonic;
104void CIRDialect::printType(Type type, DialectAsmPrinter &os)
const {
106 if (generatedTypePrinter(type, os).succeeded())
110 llvm::report_fatal_error(
"printer is missing a handler for this type");
117Type RecordType::parse(mlir::AsmParser &parser) {
118 FailureOr<AsmParser::CyclicParseReset> cyclicParseGuard;
119 const llvm::SMLoc loc = parser.getCurrentLocation();
120 const mlir::Location eLoc = parser.getEncodedSourceLoc(loc);
124 mlir::MLIRContext *context = parser.getContext();
126 if (parser.parseLess())
131 if (parser.parseOptionalKeyword(
"struct").succeeded())
132 kind = RecordKind::Struct;
133 else if (parser.parseOptionalKeyword(
"union").succeeded())
134 kind = RecordKind::Union;
135 else if (parser.parseOptionalKeyword(
"class").succeeded())
136 kind = RecordKind::Class;
138 parser.emitError(loc,
"unknown record type");
142 mlir::StringAttr
name;
143 parser.parseOptionalAttribute(name);
146 if (name && parser.parseOptionalGreater().succeeded()) {
147 RecordType
type = getChecked(eLoc, context, name, kind);
148 if (succeeded(parser.tryStartCyclicParse(type))) {
149 parser.emitError(loc,
"invalid self-reference within record");
157 RecordType
type = getChecked(eLoc, context, name, kind);
158 cyclicParseGuard = parser.tryStartCyclicParse(type);
159 if (failed(cyclicParseGuard)) {
160 parser.emitError(loc,
"record already defined");
165 if (parser.parseOptionalKeyword(
"packed").succeeded())
168 if (parser.parseOptionalKeyword(
"padded").succeeded())
172 bool incomplete =
true;
173 llvm::SmallVector<mlir::Type> members;
174 if (parser.parseOptionalKeyword(
"incomplete").failed()) {
176 const auto delimiter = AsmParser::Delimiter::Braces;
177 const auto parseElementFn = [&parser, &members]() {
178 return parser.parseType(members.emplace_back());
180 if (parser.parseCommaSeparatedList(delimiter, parseElementFn).failed())
184 if (parser.parseGreater())
188 ArrayRef<mlir::Type> membersRef(members);
189 mlir::Type
type = {};
190 if (name && incomplete) {
191 type = getChecked(eLoc, context, name, kind);
192 }
else if (!name && !incomplete) {
193 type = getChecked(eLoc, context, membersRef, packed, padded, kind);
194 }
else if (!incomplete) {
195 type = getChecked(eLoc, context, membersRef, name, packed, padded, kind);
198 if (mlir::cast<RecordType>(type).isIncomplete())
199 mlir::cast<RecordType>(type).complete(membersRef, packed, padded);
202 parser.emitError(loc,
"anonymous records must be complete");
209void RecordType::print(mlir::AsmPrinter &printer)
const {
210 FailureOr<AsmPrinter::CyclicPrintReset> cyclicPrintGuard;
214 case RecordKind::Struct:
215 printer <<
"struct ";
217 case RecordKind::Union:
220 case RecordKind::Class:
229 cyclicPrintGuard = printer.tryStartCyclicPrint(*
this);
230 if (failed(cyclicPrintGuard)) {
239 printer <<
"packed ";
242 printer <<
"padded ";
244 if (isIncomplete()) {
245 printer <<
"incomplete";
248 llvm::interleaveComma(getMembers(), printer);
256RecordType::verify(function_ref<mlir::InFlightDiagnostic()> emitError,
257 llvm::ArrayRef<mlir::Type> members, mlir::StringAttr name,
258 bool incomplete,
bool packed,
bool padded,
259 RecordType::RecordKind kind) {
260 if (name &&
name.getValue().empty())
261 return emitError() <<
"identified records cannot have an empty name";
262 return mlir::success();
265::llvm::ArrayRef<mlir::Type> RecordType::getMembers()
const {
269bool RecordType::isIncomplete()
const {
return getImpl()->incomplete; }
271mlir::StringAttr RecordType::getName()
const {
return getImpl()->name; }
273bool RecordType::getIncomplete()
const {
return getImpl()->incomplete; }
275bool RecordType::getPacked()
const {
return getImpl()->packed; }
277bool RecordType::getPadded()
const {
return getImpl()->padded; }
279cir::RecordType::RecordKind RecordType::getKind()
const {
283void RecordType::complete(ArrayRef<Type> members,
bool packed,
bool padded) {
285 if (mutate(members, packed, padded).failed())
286 llvm_unreachable(
"failed to complete record");
292Type RecordType::getLargestMember(const ::mlir::DataLayout &dataLayout)
const {
293 assert(isUnion() &&
"Only call getLargestMember on unions");
294 llvm::ArrayRef<Type> members = getMembers();
297 return *std::max_element(
298 members.begin(), getPadded() ? members.end() - 1 : members.end(),
299 [&](Type lhs, Type rhs) {
300 return dataLayout.getTypeABIAlignment(lhs) <
301 dataLayout.getTypeABIAlignment(rhs) ||
302 (dataLayout.getTypeABIAlignment(lhs) ==
303 dataLayout.getTypeABIAlignment(rhs) &&
304 dataLayout.getTypeSize(lhs) < dataLayout.getTypeSize(rhs));
308bool RecordType::isLayoutIdentical(
const RecordType &other) {
309 if (
getImpl() == other.getImpl())
312 if (getPacked() != other.getPacked())
315 return getMembers() == other.getMembers();
323PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
324 ::mlir::DataLayoutEntryListRef params)
const {
327 return llvm::TypeSize::getFixed(64);
331PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
332 ::mlir::DataLayoutEntryListRef params)
const {
339RecordType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
340 mlir::DataLayoutEntryListRef params)
const {
342 return dataLayout.getTypeSize(getLargestMember(dataLayout));
344 unsigned recordSize = computeStructSize(dataLayout);
345 return llvm::TypeSize::getFixed(recordSize * 8);
349RecordType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
350 ::mlir::DataLayoutEntryListRef params)
const {
352 return dataLayout.getTypeABIAlignment(getLargestMember(dataLayout));
357 return computeStructAlignment(dataLayout);
361RecordType::computeStructSize(
const mlir::DataLayout &dataLayout)
const {
362 assert(isComplete() &&
"Cannot get layout of incomplete records");
365 unsigned recordSize = 0;
368 for (mlir::Type ty : getMembers()) {
372 (getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
376 recordSize = llvm::alignTo(recordSize, tyAlign);
377 recordSize += dataLayout.getTypeSize(ty);
381 recordAlignment = std::max(tyAlign, recordAlignment);
386 recordSize = llvm::alignTo(recordSize, recordAlignment);
395RecordType::computeStructAlignment(
const mlir::DataLayout &dataLayout)
const {
396 assert(isComplete() &&
"Cannot get layout of incomplete records");
400 for (mlir::Type ty : getMembers())
402 std::max(dataLayout.getTypeABIAlignment(ty), recordAlignment);
404 return recordAlignment;
407uint64_t RecordType::getElementOffset(const ::mlir::DataLayout &dataLayout,
408 unsigned idx)
const {
409 assert(idx < getMembers().size() &&
"access not valid");
412 if (isUnion() || idx == 0)
415 assert(isComplete() &&
"Cannot get layout of incomplete records");
416 assert(idx < getNumElements());
417 llvm::ArrayRef<mlir::Type> members = getMembers();
422 llvm::make_range(members.begin(), std::next(members.begin(), idx))) {
424 const llvm::Align tyAlign =
425 llvm::Align(getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
428 offset = llvm::alignTo(offset, tyAlign);
431 offset += dataLayout.getTypeSize(ty);
436 const llvm::Align tyAlign = llvm::Align(
437 getPacked() ? 1 : dataLayout.getTypeABIAlignment(members[idx]));
438 offset = llvm::alignTo(offset, tyAlign);
447Type IntType::parse(mlir::AsmParser &parser) {
448 mlir::MLIRContext *context = parser.getBuilder().getContext();
449 llvm::SMLoc loc = parser.getCurrentLocation();
453 if (parser.parseLess())
457 llvm::StringRef
sign;
458 if (parser.parseKeyword(&
sign))
462 else if (
sign ==
"u")
465 parser.emitError(loc,
"expected 's' or 'u'");
469 if (parser.parseComma())
473 if (parser.parseInteger(width))
475 if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
476 parser.emitError(loc,
"expected integer width to be from ")
477 << IntType::minBitwidth() <<
" up to " << IntType::maxBitwidth();
481 if (parser.parseGreater())
484 return IntType::get(context, width, isSigned);
487void IntType::print(mlir::AsmPrinter &printer)
const {
488 char sign = isSigned() ?
's' :
'u';
489 printer <<
'<' <<
sign <<
", " << getWidth() <<
'>';
493IntType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
494 mlir::DataLayoutEntryListRef params)
const {
495 return llvm::TypeSize::getFixed(getWidth());
498uint64_t IntType::getABIAlignment(
const mlir::DataLayout &dataLayout,
499 mlir::DataLayoutEntryListRef params)
const {
500 return (uint64_t)(getWidth() / 8);
504IntType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
505 unsigned width,
bool isSigned) {
506 if (width < IntType::minBitwidth() || width > IntType::maxBitwidth())
507 return emitError() <<
"IntType only supports widths from "
508 << IntType::minBitwidth() <<
" up to "
509 << IntType::maxBitwidth();
510 return mlir::success();
514 return width == 8 || width == 16 || width == 32 || width == 64;
521const llvm::fltSemantics &SingleType::getFloatSemantics()
const {
522 return llvm::APFloat::IEEEsingle();
526SingleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
527 mlir::DataLayoutEntryListRef params)
const {
528 return llvm::TypeSize::getFixed(getWidth());
532SingleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
533 mlir::DataLayoutEntryListRef params)
const {
534 return (uint64_t)(getWidth() / 8);
537const llvm::fltSemantics &DoubleType::getFloatSemantics()
const {
538 return llvm::APFloat::IEEEdouble();
542DoubleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
543 mlir::DataLayoutEntryListRef params)
const {
544 return llvm::TypeSize::getFixed(getWidth());
548DoubleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
549 mlir::DataLayoutEntryListRef params)
const {
550 return (uint64_t)(getWidth() / 8);
553const llvm::fltSemantics &FP16Type::getFloatSemantics()
const {
554 return llvm::APFloat::IEEEhalf();
558FP16Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
559 mlir::DataLayoutEntryListRef params)
const {
560 return llvm::TypeSize::getFixed(getWidth());
563uint64_t FP16Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
564 mlir::DataLayoutEntryListRef params)
const {
565 return (uint64_t)(getWidth() / 8);
568const llvm::fltSemantics &BF16Type::getFloatSemantics()
const {
569 return llvm::APFloat::BFloat();
573BF16Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
574 mlir::DataLayoutEntryListRef params)
const {
575 return llvm::TypeSize::getFixed(getWidth());
578uint64_t BF16Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
579 mlir::DataLayoutEntryListRef params)
const {
580 return (uint64_t)(getWidth() / 8);
583const llvm::fltSemantics &FP80Type::getFloatSemantics()
const {
584 return llvm::APFloat::x87DoubleExtended();
588FP80Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
589 mlir::DataLayoutEntryListRef params)
const {
591 return llvm::TypeSize::getFixed(128);
594uint64_t FP80Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
595 mlir::DataLayoutEntryListRef params)
const {
599const llvm::fltSemantics &FP128Type::getFloatSemantics()
const {
600 return llvm::APFloat::IEEEquad();
604FP128Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
605 mlir::DataLayoutEntryListRef params)
const {
606 return llvm::TypeSize::getFixed(getWidth());
609uint64_t FP128Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
610 mlir::DataLayoutEntryListRef params)
const {
614const llvm::fltSemantics &LongDoubleType::getFloatSemantics()
const {
615 return mlir::cast<cir::FPTypeInterface>(getUnderlying()).getFloatSemantics();
619LongDoubleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
620 mlir::DataLayoutEntryListRef params)
const {
621 return mlir::cast<mlir::DataLayoutTypeInterface>(getUnderlying())
622 .getTypeSizeInBits(dataLayout, params);
626LongDoubleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
627 mlir::DataLayoutEntryListRef params)
const {
628 return mlir::cast<mlir::DataLayoutTypeInterface>(getUnderlying())
629 .getABIAlignment(dataLayout, params);
637cir::ComplexType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
638 mlir::DataLayoutEntryListRef params)
const {
644 return dataLayout.getTypeSizeInBits(getElementType()) * 2;
648cir::ComplexType::getABIAlignment(
const mlir::DataLayout &dataLayout,
649 mlir::DataLayoutEntryListRef params)
const {
655 return dataLayout.getTypeABIAlignment(getElementType());
658FuncType FuncType::clone(TypeRange inputs, TypeRange results)
const {
659 assert(results.size() == 1 &&
"expected exactly one result type");
660 return get(llvm::to_vector(inputs), results[0], isVarArg());
664static mlir::ParseResult
668 return p.parseCommaSeparatedList(
669 AsmParser::Delimiter::Paren, [&]() -> mlir::ParseResult {
671 return p.emitError(p.getCurrentLocation(),
672 "variadic `...` must be the last parameter");
673 if (succeeded(p.parseOptionalEllipsis())) {
678 if (failed(p.parseType(type)))
680 params.push_back(type);
686 mlir::ArrayRef<mlir::Type> params,
689 llvm::interleaveComma(params, p,
690 [&p](mlir::Type type) { p.printType(type); });
701mlir::Type FuncType::getReturnType()
const {
703 return cir::VoidType::get(getContext());
704 return getOptionalReturnType();
710llvm::ArrayRef<mlir::Type> FuncType::getReturnTypes()
const {
716 return getImpl()->optionalReturnType;
720bool FuncType::hasVoidReturn()
const {
return !getOptionalReturnType(); }
723FuncType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
724 llvm::ArrayRef<mlir::Type> argTypes, mlir::Type returnType,
726 if (mlir::isa_and_nonnull<cir::VoidType>(returnType))
728 <<
"!cir.func cannot have an explicit 'void' return type";
729 return mlir::success();
737BoolType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
738 ::mlir::DataLayoutEntryListRef params)
const {
739 return llvm::TypeSize::getFixed(8);
743BoolType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
744 ::mlir::DataLayoutEntryListRef params)
const {
753VPtrType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
754 mlir::DataLayoutEntryListRef params)
const {
756 return llvm::TypeSize::getFixed(64);
759uint64_t VPtrType::getABIAlignment(
const mlir::DataLayout &dataLayout,
760 mlir::DataLayoutEntryListRef params)
const {
770ArrayType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
771 ::mlir::DataLayoutEntryListRef params)
const {
772 return getSize() * dataLayout.getTypeSizeInBits(getElementType());
776ArrayType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
777 ::mlir::DataLayoutEntryListRef params)
const {
778 return dataLayout.getTypeABIAlignment(getElementType());
785llvm::TypeSize cir::VectorType::getTypeSizeInBits(
786 const ::mlir::DataLayout &dataLayout,
787 ::mlir::DataLayoutEntryListRef params)
const {
788 return llvm::TypeSize::getFixed(
789 getSize() * dataLayout.getTypeSizeInBits(getElementType()));
793cir::VectorType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
794 ::mlir::DataLayoutEntryListRef params)
const {
795 return llvm::NextPowerOf2(dataLayout.getTypeSizeInBits(*
this));
798mlir::LogicalResult cir::VectorType::verify(
799 llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
800 mlir::Type elementType, uint64_t size) {
802 return emitError() <<
"the number of vector elements must be non-zero";
811 cir::TargetAddressSpaceAttr &attr) {
812 if (failed(p.parseKeyword(
"target_address_space")))
813 return mlir::failure();
815 if (failed(p.parseLParen()))
816 return mlir::failure();
819 if (failed(p.parseInteger(targetValue)))
820 return p.emitError(p.getCurrentLocation(),
821 "expected integer address space value");
823 if (failed(p.parseRParen()))
824 return p.emitError(p.getCurrentLocation(),
825 "expected ')' after address space value");
827 mlir::MLIRContext *context = p.getBuilder().getContext();
828 attr = cir::TargetAddressSpaceAttr::get(
829 context, p.getBuilder().getUI32IntegerAttr(targetValue));
830 return mlir::success();
836 cir::TargetAddressSpaceAttr attr) {
837 p <<
"target_address_space(" << attr.getValue().getUInt() <<
")";
844void CIRDialect::registerTypes() {
847#define GET_TYPEDEF_LIST
848#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p, cir::TargetAddressSpaceAttr &attr)
void printTargetAddressSpace(mlir::AsmPrinter &p, cir::TargetAddressSpaceAttr attr)
mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p, cir::TargetAddressSpaceAttr &attr)
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)
void printTargetAddressSpace(mlir::AsmPrinter &p, cir::TargetAddressSpaceAttr attr)
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 dataLayoutPtrHandlingBasedOnLangAS()
static bool astRecordDeclAttr()