15#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
16#include "mlir/IR/BuiltinAttributes.h"
17#include "mlir/IR/DialectImplementation.h"
18#include "mlir/IR/MLIRContext.h"
19#include "mlir/Support/LLVM.h"
26#include "llvm/ADT/APFloat.h"
27#include "llvm/ADT/APInt.h"
28#include "llvm/ADT/APSInt.h"
29#include "llvm/ADT/TypeSwitch.h"
30#include "llvm/Support/MathExtras.h"
36 if (
auto sizedTy = mlir::dyn_cast<cir::SizedTypeInterface>(ty))
37 return sizedTy.isSized();
43 mlir::MLIRContext *ctx) {
44 switch (llvm::APFloat::SemanticsToEnum(sem)) {
45 case llvm::APFloat::S_IEEEhalf:
46 return cir::FP16Type::get(ctx);
47 case llvm::APFloat::S_BFloat:
48 return cir::BF16Type::get(ctx);
49 case llvm::APFloat::S_IEEEsingle:
50 return cir::SingleType::get(ctx);
51 case llvm::APFloat::S_IEEEdouble:
52 return cir::DoubleType::get(ctx);
53 case llvm::APFloat::S_x87DoubleExtended:
54 return cir::FP80Type::get(ctx);
55 case llvm::APFloat::S_IEEEquad:
56 return cir::FP128Type::get(ctx);
68static mlir::ParseResult
72 mlir::ArrayRef<mlir::Type> params,
78static mlir::ParseResult
83 mlir::ArrayRef<mlir::Type> params,
92 mlir::ptr::MemorySpaceAttrInterface &attr);
95 mlir::ptr::MemorySpaceAttrInterface attr);
99 cir::TargetAddressSpaceAttr &attr);
102 cir::TargetAddressSpaceAttr attr);
110#include "clang/CIR/Dialect/IR/CIRTypeConstraints.cpp.inc"
114#define GET_TYPEDEF_CLASSES
115#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
124Type CIRDialect::parseType(DialectAsmParser &parser)
const {
125 llvm::SMLoc typeLoc = parser.getCurrentLocation();
126 llvm::StringRef mnemonic;
130 OptionalParseResult parseResult =
131 generatedTypeParser(parser, &mnemonic, genType);
132 if (parseResult.has_value())
136 parser.emitError(typeLoc) <<
"unknown CIR type: " << mnemonic;
140void CIRDialect::printType(Type type, DialectAsmPrinter &os)
const {
142 if (generatedTypePrinter(type, os).succeeded())
146 llvm::report_fatal_error(
"printer is missing a handler for this type");
158 RecordMemberKind::Data);
163static mlir::LogicalResult
167 if (memberKinds.size() != numMembers)
168 return emitError() <<
"expected " << numMembers <<
" member kinds, got "
169 << memberKinds.size();
170 return mlir::success();
177static std::optional<RecordMemberKind>
179 llvm::StringRef keyword;
180 const llvm::SMLoc loc = parser.getCurrentLocation();
181 if (parser.parseKeyword(&keyword).failed())
183 std::optional<RecordMemberKind>
kind = symbolizeRecordMemberKind(keyword);
185 parser.emitError(loc,
"expected a record member kind");
192static mlir::ParseResult
196 assert(incomplete &&
"caller must pre-initialize incomplete to true");
197 if (parser.parseOptionalKeyword(
"incomplete").succeeded())
198 return mlir::success();
200 return parser.parseCommaSeparatedList(
201 AsmParser::Delimiter::Braces,
202 [&parser, &members, &memberKinds]() -> mlir::ParseResult {
205 return mlir::failure();
206 memberKinds.push_back(*
kind);
207 return parser.parseType(members.emplace_back());
215template <
typename RecordTy>
217 mlir::StringAttr name,
bool hasClassPrefix,
218 bool isPacked,
bool isPadded,
bool isIncomplete,
228 FailureOr<AsmPrinter::CyclicPrintReset> cyclicPrintGuard =
229 printer.tryStartCyclicPrint(self);
230 if (failed(cyclicPrintGuard)) {
235 if (hasClassPrefix || name)
238 printer <<
"packed ";
240 printer <<
"padded ";
242 printer <<
"incomplete";
245 for (
auto [idx, member] : llvm::enumerate(members)) {
248 printer << stringifyRecordMemberKind(memberKinds[idx]) <<
' ';
249 printer.printType(member);
253 printer <<
", padding = {";
254 printer.printType(padding);
262Type StructType::parse(mlir::AsmParser &parser) {
263 FailureOr<AsmParser::CyclicParseReset> cyclicParseGuard;
264 const llvm::SMLoc loc = parser.getCurrentLocation();
265 const mlir::Location eLoc = parser.getEncodedSourceLoc(loc);
268 mlir::MLIRContext *context = parser.getContext();
270 if (parser.parseLess())
274 bool is_class = parser.parseOptionalKeyword(
"class").succeeded();
276 mlir::StringAttr
name;
277 parser.parseOptionalAttribute(name);
280 if (name && parser.parseOptionalGreater().succeeded()) {
281 StructType
type = StructType::getChecked(eLoc, context, name, is_class);
282 if (succeeded(parser.tryStartCyclicParse(type))) {
283 parser.emitError(loc,
"invalid self-reference within record");
291 StructType
type = StructType::getChecked(eLoc, context, name, is_class);
292 cyclicParseGuard = parser.tryStartCyclicParse(type);
293 if (failed(cyclicParseGuard)) {
294 parser.emitError(loc,
"record already defined");
299 if (parser.parseOptionalKeyword(
"packed").succeeded())
302 if (parser.parseOptionalKeyword(
"padded").succeeded())
305 bool incomplete =
true;
306 llvm::SmallVector<mlir::Type> members;
307 llvm::SmallVector<RecordMemberKind> memberKinds;
308 if (
parseRecordBody(parser, incomplete, members, memberKinds).failed())
311 if (parser.parseGreater())
314 ArrayRef<mlir::Type> membersRef(members);
315 ArrayRef<RecordMemberKind> kindsRef(memberKinds);
316 mlir::Type
type = {};
317 if (name && incomplete) {
318 type = StructType::getChecked(eLoc, context, name, is_class);
319 }
else if (!name && !incomplete) {
320 type = StructType::getChecked(eLoc, context, membersRef, packed, padded,
324 }
else if (!incomplete) {
325 type = StructType::getChecked(eLoc, context, membersRef, name, packed,
326 padded, is_class, kindsRef);
329 if (
auto structTy = mlir::dyn_cast<StructType>(type))
330 if (structTy.isIncomplete())
331 structTy.complete(membersRef, packed, padded, kindsRef);
334 parser.emitError(loc,
"anonymous records must be complete");
341void StructType::print(mlir::AsmPrinter &printer)
const {
343 getPadded(), isIncomplete(), getMembers(), {},
348StructType::verify(function_ref<mlir::InFlightDiagnostic()> emitError,
349 llvm::ArrayRef<mlir::Type> members, mlir::StringAttr name,
350 bool incomplete,
bool packed,
bool padded,
351 llvm::ArrayRef<RecordMemberKind> member_kinds,
353 if (name &&
name.getValue().empty())
354 return emitError() <<
"identified records cannot have an empty name";
360llvm::ArrayRef<mlir::Type> StructType::getMembers()
const {
363mlir::StringAttr StructType::getName()
const {
return getImpl()->name; }
364bool StructType::isIncomplete()
const {
return getImpl()->incomplete; }
365bool StructType::getIncomplete()
const {
return getImpl()->incomplete; }
366bool StructType::getPacked()
const {
return getImpl()->packed; }
367bool StructType::getPadded()
const {
return getImpl()->padded; }
368llvm::ArrayRef<RecordMemberKind> StructType::getMemberKinds()
const {
369 return getImpl()->member_kinds;
371bool StructType::getIsClass()
const {
return getImpl()->is_class; }
373bool StructType::isABIConvertedRecord()
const {
374 return getName() &&
getName().getValue().starts_with(abi_conversion_prefix);
377mlir::StringAttr StructType::getABIConvertedName()
const {
378 assert(!isABIConvertedRecord());
379 return StringAttr::get(getContext(),
380 abi_conversion_prefix +
getName().getValue());
383void StructType::removeABIConversionNamePrefix() {
384 mlir::StringAttr recordName =
getName();
385 if (recordName && recordName.getValue().starts_with(abi_conversion_prefix))
386 getImpl()->name = mlir::StringAttr::get(
387 recordName.getValue().drop_front(
sizeof(abi_conversion_prefix) - 1),
388 recordName.getType());
391void StructType::complete(ArrayRef<Type> members,
bool packed,
bool padded,
392 ArrayRef<RecordMemberKind> memberKinds) {
394 if (mutate(members, packed, padded, memberKinds).failed())
395 llvm_unreachable(
"failed to complete struct");
398bool StructType::isLayoutIdentical(
const StructType &other) {
399 if (
getImpl() == other.getImpl())
401 if (getPacked() != other.getPacked())
403 return getMembers() == other.getMembers();
410Type UnionType::parse(mlir::AsmParser &parser) {
411 FailureOr<AsmParser::CyclicParseReset> cyclicParseGuard;
412 const llvm::SMLoc loc = parser.getCurrentLocation();
413 const mlir::Location eLoc = parser.getEncodedSourceLoc(loc);
416 mlir::MLIRContext *context = parser.getContext();
418 if (parser.parseLess())
421 mlir::StringAttr
name;
422 parser.parseOptionalAttribute(name);
425 if (name && parser.parseOptionalGreater().succeeded()) {
426 UnionType
type = UnionType::getChecked(eLoc, context, name);
427 if (succeeded(parser.tryStartCyclicParse(type))) {
428 parser.emitError(loc,
"invalid self-reference within record");
436 UnionType
type = UnionType::getChecked(eLoc, context, name);
437 cyclicParseGuard = parser.tryStartCyclicParse(type);
438 if (failed(cyclicParseGuard)) {
439 parser.emitError(loc,
"record already defined");
444 if (parser.parseOptionalKeyword(
"packed").succeeded())
447 bool incomplete =
true;
448 llvm::SmallVector<mlir::Type> members;
449 llvm::SmallVector<RecordMemberKind> memberKinds;
450 if (
parseRecordBody(parser, incomplete, members, memberKinds).failed())
455 if (!incomplete && parser.parseOptionalComma().succeeded()) {
456 if (parser.parseKeyword(
"padding").failed())
458 if (parser.parseEqual().failed())
460 if (parser.parseLBrace().failed())
462 const llvm::SMLoc paddingLoc = parser.getCurrentLocation();
463 llvm::StringRef paddingKeyword;
466 parser.emitError(paddingLoc,
"a union's tail padding takes no kind mark");
469 if (parser.parseType(padding).failed())
471 if (parser.parseRBrace().failed())
475 if (parser.parseGreater())
478 ArrayRef<mlir::Type> membersRef(members);
479 ArrayRef<RecordMemberKind> kindsRef(memberKinds);
480 mlir::Type
type = {};
481 if (name && incomplete) {
482 type = UnionType::getChecked(eLoc, context, name);
483 }
else if (!name && !incomplete) {
484 type = UnionType::getChecked(eLoc, context, membersRef, packed, padding,
488 }
else if (!incomplete) {
489 type = UnionType::getChecked(eLoc, context, membersRef, name, packed,
493 if (
auto unionTy = mlir::dyn_cast<UnionType>(type))
494 if (unionTy.isIncomplete())
495 unionTy.complete(membersRef, packed, padding, kindsRef);
498 parser.emitError(loc,
"anonymous records must be complete");
505void UnionType::print(mlir::AsmPrinter &printer)
const {
507 getPacked(),
false, isIncomplete(), getMembers(),
508 getPadding(), getMemberKinds());
512UnionType::verify(function_ref<mlir::InFlightDiagnostic()> emitError,
513 llvm::ArrayRef<mlir::Type> members, mlir::StringAttr name,
514 bool incomplete,
bool packed, mlir::Type padding,
515 llvm::ArrayRef<RecordMemberKind> member_kinds) {
516 if (name &&
name.getValue().empty())
517 return emitError() <<
"identified records cannot have an empty name";
521 if (llvm::is_contained(member_kinds, RecordMemberKind::Pad))
522 return emitError() <<
"a union member cannot be marked pad";
527llvm::ArrayRef<mlir::Type> UnionType::getMembers()
const {
530mlir::StringAttr UnionType::getName()
const {
return getImpl()->name; }
531bool UnionType::isIncomplete()
const {
return getImpl()->incomplete; }
532bool UnionType::getIncomplete()
const {
return getImpl()->incomplete; }
533bool UnionType::getPacked()
const {
return getImpl()->packed; }
534bool UnionType::getPadded()
const {
return getPadding() ?
true :
false; }
535mlir::Type UnionType::getPadding()
const {
return getImpl()->padding; }
536llvm::ArrayRef<RecordMemberKind> UnionType::getMemberKinds()
const {
537 return getImpl()->member_kinds;
540bool UnionType::isABIConvertedRecord()
const {
541 return getName() &&
getName().getValue().starts_with(abi_conversion_prefix);
544mlir::StringAttr UnionType::getABIConvertedName()
const {
545 assert(!isABIConvertedRecord());
546 return StringAttr::get(getContext(),
547 abi_conversion_prefix +
getName().getValue());
550void UnionType::removeABIConversionNamePrefix() {
551 mlir::StringAttr recordName =
getName();
552 if (recordName && recordName.getValue().starts_with(abi_conversion_prefix))
553 getImpl()->name = mlir::StringAttr::get(
554 recordName.getValue().drop_front(
sizeof(abi_conversion_prefix) - 1),
555 recordName.getType());
558void UnionType::complete(ArrayRef<Type> members,
bool packed,
560 ArrayRef<RecordMemberKind> memberKinds) {
562 if (mutate(members, packed, padding, memberKinds).failed())
563 llvm_unreachable(
"failed to complete union");
567UnionType::getUnionStorageType(
const mlir::DataLayout &dataLayout)
const {
568 return getUnionStorageType(dataLayout, getMembers());
571mlir::Type UnionType::getUnionStorageType(
const mlir::DataLayout &dataLayout,
572 llvm::ArrayRef<mlir::Type> members) {
575 return *std::max_element(
576 members.begin(), members.end(), [&](mlir::Type lhs, mlir::Type rhs) {
577 return dataLayout.getTypeABIAlignment(lhs) <
578 dataLayout.getTypeABIAlignment(rhs) ||
579 (dataLayout.getTypeABIAlignment(lhs) ==
580 dataLayout.getTypeABIAlignment(rhs) &&
581 dataLayout.getTypeSize(lhs) < dataLayout.getTypeSize(rhs));
585bool UnionType::isLayoutIdentical(
const UnionType &other) {
586 if (
getImpl() == other.getImpl())
588 return getMembers() == other.getMembers() &&
589 getPadding() == other.getPadding();
597 if (
auto s = mlir::dyn_cast<StructType>(*
this))
598 return s.getMembers();
599 return mlir::cast<UnionType>(*this).getMembers();
602 if (
auto s = mlir::dyn_cast<StructType>(*
this))
604 return mlir::cast<UnionType>(*this).getName();
607 if (
auto s = mlir::dyn_cast<StructType>(*
this))
608 return s.isIncomplete();
609 return mlir::cast<UnionType>(*this).isIncomplete();
612 if (
auto s = mlir::dyn_cast<StructType>(*
this))
613 return s.getPacked();
614 return mlir::cast<UnionType>(*this).getPacked();
617 if (
auto s = mlir::dyn_cast<StructType>(*
this))
618 return s.getPadded();
619 return mlir::cast<UnionType>(*this).getPadded();
622 if (
auto s = mlir::dyn_cast<StructType>(*
this))
623 return s.getMemberKinds();
624 return mlir::cast<UnionType>(*this).getMemberKinds();
627 if (
auto s = mlir::dyn_cast<StructType>(*
this))
632 if (
auto s = mlir::dyn_cast<StructType>(*
this))
637 if (mlir::isa<UnionType>(*
this))
639 return mlir::cast<StructType>(*this).getKindAsStr();
647 if (
auto s = mlir::dyn_cast<StructType>(*
this))
648 return s.complete(members, packed, padded, memberKinds);
650 assert((!padded || padding) &&
651 "padded=true requires a non-null padding type");
652 return mlir::cast<UnionType>(*this).complete(members, packed, padding,
656 unsigned idx)
const {
657 if (mlir::isa<UnionType>(*
this))
659 return mlir::cast<StructType>(*this).getElementOffset(dataLayout, idx);
662 if (
auto s = mlir::dyn_cast<StructType>(*
this)) {
663 if (
auto so = mlir::dyn_cast<StructType>(other))
664 return s.isLayoutIdentical(so);
667 if (
auto u = mlir::dyn_cast<UnionType>(*
this)) {
668 if (
auto uo = mlir::dyn_cast<UnionType>(other))
669 return u.isLayoutIdentical(uo);
675 if (
auto s = mlir::dyn_cast<StructType>(*
this))
676 return s.isABIConvertedRecord();
677 return mlir::cast<UnionType>(*this).isABIConvertedRecord();
680 if (
auto s = mlir::dyn_cast<StructType>(*
this))
681 return s.getABIConvertedName();
682 return mlir::cast<UnionType>(*this).getABIConvertedName();
685 if (
auto s = mlir::dyn_cast<StructType>(*
this))
686 return s.removeABIConversionNamePrefix();
687 return mlir::cast<UnionType>(*this).removeABIConversionNamePrefix();
696 return kind == RecordMemberKind::Data;
707constexpr static uint64_t kBitsInByte = 8;
710constexpr static uint64_t kDefaultPointerSizeBits = 64;
711constexpr static uint64_t kDefaultPointerAlignment = 8;
715cir::PtrSpecAttr getPointerSpec(mlir::DataLayoutEntryListRef params,
716 cir::PointerType type) {
719 for (mlir::DataLayoutEntryInterface entry : params) {
720 if (!entry.isTypeEntry())
723 mlir::cast<cir::PointerType>(mlir::cast<mlir::Type>(entry.getKey()));
724 if (key.getAddrSpace())
726 if (
auto spec = mlir::dyn_cast<cir::PtrSpecAttr>(entry.getValue()))
729 return cir::PtrSpecAttr::get(type.getContext(), kDefaultPointerSizeBits,
730 kDefaultPointerAlignment * kBitsInByte,
731 kDefaultPointerAlignment * kBitsInByte,
732 kDefaultPointerSizeBits);
737PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
738 ::mlir::DataLayoutEntryListRef params)
const {
739 return llvm::TypeSize::getFixed(getPointerSpec(params, *
this).getSize());
743PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
744 ::mlir::DataLayoutEntryListRef params)
const {
745 return getPointerSpec(params, *
this).getAbi() / kBitsInByte;
748uint64_t PointerType::getPreferredAlignment(
749 const ::mlir::DataLayout &dataLayout,
750 ::mlir::DataLayoutEntryListRef params)
const {
751 return getPointerSpec(params, *
this).getPreferred() / kBitsInByte;
754std::optional<uint64_t>
755PointerType::getIndexBitwidth(const ::mlir::DataLayout &dataLayout,
756 ::mlir::DataLayoutEntryListRef params)
const {
757 cir::PtrSpecAttr spec = getPointerSpec(params, *
this);
758 if (spec.getIndex() == cir::PtrSpecAttr::kOptionalSpecValue)
759 return spec.getSize();
760 return spec.getIndex();
764PointerType::verifyEntries(mlir::DataLayoutEntryListRef entries,
765 mlir::Location loc)
const {
766 for (mlir::DataLayoutEntryInterface entry : entries) {
767 if (!entry.isTypeEntry())
769 auto key = mlir::cast<PointerType>(mlir::cast<mlir::Type>(entry.getKey()));
770 if (!mlir::isa<cir::PtrSpecAttr>(entry.getValue()))
771 return mlir::emitError(loc) <<
"expected layout attribute for " << key
772 <<
" to be a #cir.ptr_spec attribute";
773 if (!mlir::isa<cir::VoidType>(key.getPointee()))
774 return mlir::emitError(loc) <<
"expected !cir.ptr data layout entry for "
775 << key <<
" to use !cir.void as pointee";
777 if (key.getAddrSpace())
778 return mlir::emitError(loc)
779 <<
"!cir.ptr data layout entries are currently limited to the "
780 "default address space";
782 return mlir::success();
785bool PointerType::areCompatible(
786 mlir::DataLayoutEntryListRef oldLayout,
787 mlir::DataLayoutEntryListRef newLayout, mlir::DataLayoutSpecInterface,
788 const mlir::DataLayoutIdentifiedEntryMap &)
const {
791 cir::PtrSpecAttr oldSpec = getPointerSpec(oldLayout, *
this);
794 for (mlir::DataLayoutEntryInterface newEntry : newLayout) {
795 if (!newEntry.isTypeEntry())
797 auto newSpec = mlir::cast<cir::PtrSpecAttr>(newEntry.getValue());
798 if (size != newSpec.getSize() || abi < newSpec.getAbi() ||
799 abi % newSpec.getAbi() != 0)
806StructType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
807 mlir::DataLayoutEntryListRef params)
const {
808 auto recordSize =
static_cast<uint64_t>(computeStructSize(dataLayout));
809 return llvm::TypeSize::getFixed(recordSize * 8);
813StructType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
814 ::mlir::DataLayoutEntryListRef params)
const {
818 return computeStructAlignment(dataLayout);
825UnionType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
826 mlir::DataLayoutEntryListRef params)
const {
827 llvm::TypeSize size = llvm::TypeSize::getFixed(0);
828 if (mlir::Type storage = getUnionStorageType(dataLayout))
829 size += dataLayout.getTypeSizeInBits(storage);
830 if (mlir::Type pad = getPadding())
831 size += dataLayout.getTypeSizeInBits(pad);
836UnionType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
837 ::mlir::DataLayoutEntryListRef params)
const {
838 mlir::Type storage = getUnionStorageType(dataLayout);
841 return dataLayout.getTypeABIAlignment(storage);
845StructType::computeStructSize(
const mlir::DataLayout &dataLayout)
const {
846 assert(isComplete() &&
"Cannot get layout of incomplete records");
849 unsigned recordSize = 0;
852 for (mlir::Type ty : getMembers()) {
856 (getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
860 recordSize = llvm::alignTo(recordSize, tyAlign);
861 recordSize += dataLayout.getTypeSize(ty);
865 recordAlignment = std::max(tyAlign, recordAlignment);
870 recordSize = llvm::alignTo(recordSize, recordAlignment);
875StructType::computeStructDataSize(
const mlir::DataLayout &dataLayout)
const {
876 assert(isComplete() &&
"Cannot get layout of incomplete records");
883 auto members = getMembers();
884 unsigned numMembers =
885 getPadded() && members.size() > 1 ? members.size() - 1 : members.size();
886 unsigned recordSize = 0;
887 for (
unsigned i = 0; i < numMembers; ++i) {
888 mlir::Type ty = members[i];
890 (getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
891 recordSize = llvm::alignTo(recordSize, tyAlign);
892 recordSize += dataLayout.getTypeSize(ty);
902StructType::computeStructAlignment(
const mlir::DataLayout &dataLayout)
const {
903 assert(isComplete() &&
"Cannot get layout of incomplete records");
906 for (mlir::Type ty : getMembers())
908 std::max(dataLayout.getTypeABIAlignment(ty), recordAlignment);
909 return recordAlignment;
912uint64_t StructType::getElementOffset(const ::mlir::DataLayout &dataLayout,
913 unsigned idx)
const {
914 assert(idx < getMembers().size() &&
"access not valid");
918 assert(isComplete() &&
"Cannot get layout of incomplete records");
919 assert(idx < getNumElements());
920 llvm::ArrayRef<mlir::Type> members = getMembers();
924 llvm::make_range(members.begin(), std::next(members.begin(), idx))) {
925 const llvm::Align tyAlign =
926 llvm::Align(getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
927 offset = llvm::alignTo(offset, tyAlign);
928 offset += dataLayout.getTypeSize(ty);
931 const llvm::Align tyAlign = llvm::Align(
932 getPacked() ? 1 : dataLayout.getTypeABIAlignment(members[idx]));
933 offset = llvm::alignTo(offset, tyAlign);
941Type IntType::parse(mlir::AsmParser &parser) {
942 mlir::MLIRContext *context = parser.getBuilder().getContext();
943 llvm::SMLoc loc = parser.getCurrentLocation();
947 if (parser.parseLess())
951 llvm::StringRef
sign;
952 if (parser.parseKeyword(&
sign))
956 else if (
sign ==
"u")
959 parser.emitError(loc,
"expected 's' or 'u'");
963 if (parser.parseComma())
967 if (parser.parseInteger(width))
969 if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
970 parser.emitError(loc,
"expected integer width to be from ")
971 << IntType::minBitwidth() <<
" up to " << IntType::maxBitwidth();
975 bool isBitInt =
false;
976 if (succeeded(parser.parseOptionalComma())) {
978 if (parser.parseKeyword(&kw) || kw !=
"bitint") {
979 parser.emitError(loc,
"expected 'bitint'");
985 if (parser.parseGreater())
988 return IntType::get(context, width, isSigned, isBitInt);
991void IntType::print(mlir::AsmPrinter &printer)
const {
992 char sign = isSigned() ?
's' :
'u';
993 printer <<
'<' <<
sign <<
", " << getWidth();
995 printer <<
", bitint";
1000IntType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1001 mlir::DataLayoutEntryListRef params)
const {
1002 return llvm::TypeSize::getFixed(getWidth());
1005uint64_t IntType::getABIAlignment(
const mlir::DataLayout &dataLayout,
1006 mlir::DataLayoutEntryListRef params)
const {
1007 unsigned width = getWidth();
1012 std::min(llvm::PowerOf2Ceil(width),
static_cast<uint64_t>(64));
1013 return std::max(alignBits / 8,
static_cast<uint64_t>(1));
1020 uint64_t alignBits = llvm::PowerOf2Ceil(width);
1021 return std::max(alignBits / 8,
static_cast<uint64_t>(1));
1025IntType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1026 unsigned width,
bool isSigned,
bool isBitInt) {
1027 if (width < IntType::minBitwidth() || width > IntType::maxBitwidth())
1028 return emitError() <<
"IntType only supports widths from "
1029 << IntType::minBitwidth() <<
" up to "
1030 << IntType::maxBitwidth();
1031 return mlir::success();
1035 return width == 8 || width == 16 || width == 32 || width == 64;
1042const llvm::fltSemantics &SingleType::getFloatSemantics()
const {
1043 return llvm::APFloat::IEEEsingle();
1047SingleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1048 mlir::DataLayoutEntryListRef params)
const {
1049 return llvm::TypeSize::getFixed(getWidth());
1053SingleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
1054 mlir::DataLayoutEntryListRef params)
const {
1055 return (uint64_t)(getWidth() / 8);
1058const llvm::fltSemantics &DoubleType::getFloatSemantics()
const {
1059 return llvm::APFloat::IEEEdouble();
1063DoubleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1064 mlir::DataLayoutEntryListRef params)
const {
1065 return llvm::TypeSize::getFixed(getWidth());
1069DoubleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
1070 mlir::DataLayoutEntryListRef params)
const {
1071 return (uint64_t)(getWidth() / 8);
1074const llvm::fltSemantics &FP16Type::getFloatSemantics()
const {
1075 return llvm::APFloat::IEEEhalf();
1079FP16Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1080 mlir::DataLayoutEntryListRef params)
const {
1081 return llvm::TypeSize::getFixed(getWidth());
1084uint64_t FP16Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
1085 mlir::DataLayoutEntryListRef params)
const {
1086 return (uint64_t)(getWidth() / 8);
1089const llvm::fltSemantics &BF16Type::getFloatSemantics()
const {
1090 return llvm::APFloat::BFloat();
1094BF16Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1095 mlir::DataLayoutEntryListRef params)
const {
1096 return llvm::TypeSize::getFixed(getWidth());
1099uint64_t BF16Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
1100 mlir::DataLayoutEntryListRef params)
const {
1101 return (uint64_t)(getWidth() / 8);
1104const llvm::fltSemantics &FP80Type::getFloatSemantics()
const {
1105 return llvm::APFloat::x87DoubleExtended();
1109FP80Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1110 mlir::DataLayoutEntryListRef params)
const {
1112 return llvm::TypeSize::getFixed(128);
1115uint64_t FP80Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
1116 mlir::DataLayoutEntryListRef params)
const {
1120const llvm::fltSemantics &FP128Type::getFloatSemantics()
const {
1121 return llvm::APFloat::IEEEquad();
1125FP128Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1126 mlir::DataLayoutEntryListRef params)
const {
1127 return llvm::TypeSize::getFixed(getWidth());
1130uint64_t FP128Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
1131 mlir::DataLayoutEntryListRef params)
const {
1135const llvm::fltSemantics &LongDoubleType::getFloatSemantics()
const {
1136 return mlir::cast<cir::FPTypeInterface>(getUnderlying()).getFloatSemantics();
1140LongDoubleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1141 mlir::DataLayoutEntryListRef params)
const {
1142 return mlir::cast<mlir::DataLayoutTypeInterface>(getUnderlying())
1143 .getTypeSizeInBits(dataLayout, params);
1147LongDoubleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
1148 mlir::DataLayoutEntryListRef params)
const {
1149 return mlir::cast<mlir::DataLayoutTypeInterface>(getUnderlying())
1150 .getABIAlignment(dataLayout, params);
1158cir::ComplexType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1159 mlir::DataLayoutEntryListRef params)
const {
1165 return dataLayout.getTypeSizeInBits(getElementType()) * 2;
1169cir::ComplexType::getABIAlignment(
const mlir::DataLayout &dataLayout,
1170 mlir::DataLayoutEntryListRef params)
const {
1176 return dataLayout.getTypeABIAlignment(getElementType());
1179FuncType FuncType::clone(TypeRange inputs, TypeRange results)
const {
1180 assert(results.size() == 1 &&
"expected exactly one result type");
1181 return get(llvm::to_vector(inputs), results[0], isVarArg());
1185static mlir::ParseResult
1189 return p.parseCommaSeparatedList(
1190 AsmParser::Delimiter::Paren, [&]() -> mlir::ParseResult {
1192 return p.emitError(p.getCurrentLocation(),
1193 "variadic `...` must be the last parameter");
1194 if (succeeded(p.parseOptionalEllipsis())) {
1199 if (failed(p.parseType(type)))
1201 params.push_back(type);
1207 mlir::ArrayRef<mlir::Type> params,
1210 llvm::interleaveComma(params, p,
1211 [&p](mlir::Type type) { p.printType(type); });
1213 if (!params.empty())
1222mlir::Type FuncType::getReturnType()
const {
1223 if (hasVoidReturn())
1224 return cir::VoidType::get(getContext());
1225 return getOptionalReturnType();
1231llvm::ArrayRef<mlir::Type> FuncType::getReturnTypes()
const {
1232 if (hasVoidReturn())
1237 return getImpl()->optionalReturnType;
1241bool FuncType::hasVoidReturn()
const {
return !getOptionalReturnType(); }
1244FuncType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1245 llvm::ArrayRef<mlir::Type> argTypes, mlir::Type returnType,
1247 if (mlir::isa_and_nonnull<cir::VoidType>(returnType))
1249 <<
"!cir.func cannot have an explicit 'void' return type";
1250 return mlir::success();
1262 auto voidPtrTy = cir::PointerType::get(cir::VoidType::get(ctx));
1263 mlir::Type fields[2]{voidPtrTy, voidPtrTy};
1264 return cir::StructType::get(ctx, fields,
false,
1270MethodType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1271 mlir::DataLayoutEntryListRef params)
const {
1276MethodType::getABIAlignment(
const mlir::DataLayout &dataLayout,
1277 mlir::DataLayoutEntryListRef params)
const {
1279 .getABIAlignment(dataLayout, params);
1287BoolType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
1288 ::mlir::DataLayoutEntryListRef params)
const {
1289 return llvm::TypeSize::getFixed(8);
1293BoolType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
1294 ::mlir::DataLayoutEntryListRef params)
const {
1303 mlir::MLIRContext *ctx) {
1307 auto voidPtrTy = cir::PointerType::get(cir::VoidType::get(ctx));
1308 uint64_t width = dataLayout.getTypeIndexBitwidth(voidPtrTy).value_or(
1309 dataLayout.getTypeSizeInBits(voidPtrTy).getFixedValue());
1310 return cir::IntType::get(ctx, width,
true);
1314DataMemberType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
1315 ::mlir::DataLayoutEntryListRef params)
const {
1317 return dataLayout.getTypeSizeInBits(
1322DataMemberType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
1323 ::mlir::DataLayoutEntryListRef params)
const {
1325 return dataLayout.getTypeABIAlignment(
1334VPtrType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1335 mlir::DataLayoutEntryListRef params)
const {
1337 return dataLayout.getTypeSizeInBits(
1338 cir::PointerType::get(cir::VoidType::get(getContext())));
1341uint64_t VPtrType::getABIAlignment(
const mlir::DataLayout &dataLayout,
1342 mlir::DataLayoutEntryListRef params)
const {
1343 return dataLayout.getTypeABIAlignment(
1344 cir::PointerType::get(cir::VoidType::get(getContext())));
1352ArrayType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
1353 ::mlir::DataLayoutEntryListRef params)
const {
1354 return getSize() * dataLayout.getTypeSizeInBits(getElementType());
1358ArrayType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
1359 ::mlir::DataLayoutEntryListRef params)
const {
1360 return dataLayout.getTypeABIAlignment(getElementType());
1367llvm::TypeSize cir::VectorType::getTypeSizeInBits(
1368 const ::mlir::DataLayout &dataLayout,
1369 ::mlir::DataLayoutEntryListRef params)
const {
1370 return llvm::TypeSize::getFixed(
1371 getSize() * dataLayout.getTypeSizeInBits(getElementType()));
1375cir::VectorType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
1376 ::mlir::DataLayoutEntryListRef params)
const {
1378 return llvm::PowerOf2Ceil(
1379 llvm::divideCeil(dataLayout.getTypeSizeInBits(*
this), 8u));
1382mlir::LogicalResult cir::VectorType::verify(
1383 llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1384 mlir::Type elementType, uint64_t size,
bool scalable) {
1386 return emitError() <<
"the number of vector elements must be non-zero";
1390mlir::Type cir::VectorType::parse(::mlir::AsmParser &odsParser) {
1392 llvm::SMLoc odsLoc = odsParser.getCurrentLocation();
1393 mlir::Builder odsBuilder(odsParser.getContext());
1394 mlir::FailureOr<::mlir::Type> elementType;
1395 mlir::FailureOr<uint64_t> size;
1396 bool isScalabe =
false;
1399 if (odsParser.parseLess())
1403 if (odsParser.parseOptionalLSquare().succeeded())
1407 size = mlir::FieldParser<uint64_t>::parse(odsParser);
1408 if (mlir::failed(size)) {
1409 odsParser.emitError(odsParser.getCurrentLocation(),
1410 "failed to parse CIR_VectorType parameter 'size' which "
1411 "is to be a `uint64_t`");
1417 if (isScalabe && odsParser.parseRSquare().failed()) {
1418 odsParser.emitError(odsParser.getCurrentLocation(),
1419 "missing closing `]` for scalable dim size");
1424 if (odsParser.parseKeyword(
"x"))
1428 elementType = mlir::FieldParser<::mlir::Type>::parse(odsParser);
1429 if (mlir::failed(elementType)) {
1430 odsParser.emitError(odsParser.getCurrentLocation(),
1431 "failed to parse CIR_VectorType parameter "
1432 "'elementType' which is to be a `mlir::Type`");
1437 if (odsParser.parseGreater())
1439 return odsParser.getChecked<VectorType>(odsLoc, odsParser.getContext(),
1440 mlir::Type((*elementType)),
1444void cir::VectorType::print(mlir::AsmPrinter &odsPrinter)
const {
1445 mlir::Builder odsBuilder(getContext());
1447 if (this->getIsScalable())
1450 odsPrinter.printStrippedAttrOrType(getSize());
1451 if (this->getIsScalable())
1453 odsPrinter <<
' ' <<
"x";
1455 odsPrinter.printStrippedAttrOrType(getElementType());
1464 mlir::ptr::MemorySpaceAttrInterface memorySpace) {
1465 return mlir::isa<cir::LangAddressSpaceAttr, cir::TargetAddressSpaceAttr>(
1472 case LangAS::Default:
1473 return LangAddressSpace::Default;
1474 case LangAS::opencl_global:
1475 return LangAddressSpace::OffloadGlobal;
1476 case LangAS::opencl_local:
1477 case LangAS::cuda_shared:
1480 return LangAddressSpace::OffloadLocal;
1481 case LangAS::cuda_device:
1482 return LangAddressSpace::OffloadGlobal;
1483 case LangAS::opencl_constant:
1484 case LangAS::cuda_constant:
1485 return LangAddressSpace::OffloadConstant;
1486 case LangAS::opencl_private:
1487 return LangAddressSpace::OffloadPrivate;
1488 case LangAS::opencl_generic:
1489 return LangAddressSpace::OffloadGeneric;
1490 case LangAS::opencl_global_device:
1491 return LangAddressSpace::OffloadGlobalDevice;
1492 case LangAS::opencl_global_host:
1493 return LangAddressSpace::OffloadGlobalHost;
1494 case LangAS::sycl_global:
1495 case LangAS::sycl_global_device:
1496 case LangAS::sycl_global_host:
1497 case LangAS::sycl_local:
1498 case LangAS::sycl_private:
1499 case LangAS::ptr32_sptr:
1500 case LangAS::ptr32_uptr:
1502 case LangAS::hlsl_groupshared:
1503 case LangAS::wasm_funcref:
1504 llvm_unreachable(
"NYI");
1506 llvm_unreachable(
"unknown/unsupported clang language address space");
1512 mlir::ptr::MemorySpaceAttrInterface &attr) {
1514 llvm::SMLoc loc = p.getCurrentLocation();
1518 if (p.parseOptionalKeyword(
"target_address_space").succeeded()) {
1520 if (p.parseLParen())
1521 return p.emitError(loc,
"expected '(' after 'target_address_space'");
1523 if (p.parseInteger(val))
1524 return p.emitError(loc,
"expected target address space value");
1526 if (p.parseRParen())
1527 return p.emitError(loc,
"expected ')'");
1529 attr = cir::TargetAddressSpaceAttr::get(p.getContext(), val);
1530 return mlir::success();
1534 if (p.parseOptionalKeyword(
"lang_address_space").succeeded()) {
1535 if (p.parseLParen())
1536 return p.emitError(loc,
"expected '(' after 'lang_address_space'");
1538 mlir::FailureOr<cir::LangAddressSpace> result =
1539 mlir::FieldParser<cir::LangAddressSpace>::parse(p);
1540 if (mlir::failed(result))
1541 return mlir::failure();
1543 if (p.parseRParen())
1544 return p.emitError(loc,
"expected ')'");
1546 attr = cir::LangAddressSpaceAttr::get(p.getContext(), result.value());
1547 return mlir::success();
1550 llvm::StringRef keyword;
1551 if (p.parseOptionalKeyword(&keyword).succeeded())
1552 return p.emitError(loc,
"unknown address space specifier '")
1553 << keyword <<
"'; expected 'target_address_space' or "
1554 <<
"'lang_address_space'";
1556 return mlir::success();
1560 mlir::ptr::MemorySpaceAttrInterface attr) {
1564 if (
auto language = dyn_cast<cir::LangAddressSpaceAttr>(attr)) {
1565 p <<
"lang_address_space("
1566 << cir::stringifyLangAddressSpace(language.getValue()) <<
')';
1570 if (
auto target = dyn_cast<cir::TargetAddressSpaceAttr>(attr)) {
1571 p <<
"target_address_space(" << target.getValue() <<
')';
1575 llvm_unreachable(
"unexpected address-space attribute kind");
1578mlir::OptionalParseResult
1580 mlir::ptr::MemorySpaceAttrInterface &attr) {
1582 mlir::SMLoc loc = p.getCurrentLocation();
1584 return p.emitError(loc,
"failed to parse Address Space Value for GlobalOp");
1585 return mlir::success();
1589 mlir::ptr::MemorySpaceAttrInterface attr) {
1594 mlir::ptr::MemorySpaceAttrInterface addrSpace) {
1596 mlir::dyn_cast_if_present<cir::LangAddressSpaceAttr>(addrSpace))
1597 if (langAS.getValue() == cir::LangAddressSpace::Default)
1602mlir::ptr::MemorySpaceAttrInterface
1606 if (langAS == LangAS::Default)
1607 return cir::LangAddressSpaceAttr::get(&ctx, cir::LangAddressSpace::Default);
1611 return cir::TargetAddressSpaceAttr::get(&ctx, targetAS);
1624 return expected == cirAS;
1631mlir::LogicalResult cir::PointerType::verify(
1632 llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1633 mlir::Type pointee, mlir::ptr::MemorySpaceAttrInterface addrSpace) {
1636 return emitError() <<
"unsupported address space attribute; expected "
1637 "'target_address_space' or 'lang_address_space'";
1648void CIRDialect::registerTypes() {
1651#define GET_TYPEDEF_LIST
1652#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
Provides definitions for the various language-specific address spaces.
void printAddressSpaceValue(mlir::AsmPrinter &p, cir::LangAddressSpace addrSpace)
mlir::ParseResult parseAddressSpaceValue(mlir::AsmParser &p, cir::LangAddressSpace &addrSpace)
void printGlobalAddressSpaceValue(mlir::AsmPrinter &printer, cir::GlobalOp op, mlir::ptr::MemorySpaceAttrInterface attr)
mlir::OptionalParseResult parseGlobalAddressSpaceValue(mlir::AsmParser &p, mlir::ptr::MemorySpaceAttrInterface &attr)
static void printRecordBody(mlir::AsmPrinter &printer, RecordTy self, mlir::StringAttr name, bool hasClassPrefix, bool isPacked, bool isPadded, bool isIncomplete, llvm::ArrayRef< mlir::Type > members, mlir::Type padding, llvm::ArrayRef< RecordMemberKind > memberKinds)
Print a complete CIR record body: '<' ['class '] [name] ['packed '] ['padded '] body '>' where body i...
void printAddressSpaceValue(mlir::AsmPrinter &printer, mlir::ptr::MemorySpaceAttrInterface attr)
static const llvm::StringRef memberKindMarks[]
The keywords that spell a member kind.
mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p, cir::TargetAddressSpaceAttr &attr)
static mlir::LogicalResult verifyRecordMemberKinds(function_ref< mlir::InFlightDiagnostic()> emitError, size_t numMembers, llvm::ArrayRef< RecordMemberKind > memberKinds)
An incomplete record has no members, so a kind for one is caught by the same check.
mlir::ParseResult parseAddressSpaceValue(mlir::AsmParser &p, mlir::ptr::MemorySpaceAttrInterface &attr)
static mlir::ParseResult parseFuncTypeParams(mlir::AsmParser &p, llvm::SmallVector< mlir::Type > ¶ms, bool &isVarArg)
static mlir::Type getMethodLayoutType(mlir::MLIRContext *ctx)
static void printFuncTypeParams(mlir::AsmPrinter &p, mlir::ArrayRef< mlir::Type > params, bool isVarArg)
static mlir::ParseResult parseRecordBody(mlir::AsmParser &parser, bool &incomplete, llvm::SmallVector< mlir::Type > &members, llvm::SmallVectorImpl< RecordMemberKind > &memberKinds)
Parse "incomplete" or "{mark type, mark type, ...}", writing results into incomplete,...
static std::optional< RecordMemberKind > parseMemberKind(mlir::AsmParser &parser)
void printTargetAddressSpace(mlir::AsmPrinter &p, cir::TargetAddressSpaceAttr attr)
static mlir::Type getDataMemberLayoutType(const mlir::DataLayout &dataLayout, mlir::MLIRContext *ctx)
static LiveVariablesImpl & getImpl(void *x)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
bool isLayoutIdentical(const RecordType &other)
bool isABIConvertedRecord() const
bool isIncomplete() const
void complete(llvm::ArrayRef< mlir::Type > members, bool packed, bool padded, mlir::Type padding, llvm::ArrayRef< RecordMemberKind > memberKinds)
bool isEmptyForABI() const
Whether no member holds data.
std::string getPrefixedName() const
llvm::ArrayRef< mlir::Type > getMembers() const
void removeABIConversionNamePrefix()
static llvm::SmallVector< RecordMemberKind > getAllDataKinds(llvm::ArrayRef< mlir::Type > members)
One Data kind per member.
mlir::StringAttr getName() const
mlir::StringAttr getABIConvertedName() const
std::string getKindAsStr() const
llvm::ArrayRef< RecordMemberKind > getMemberKinds() const
uint64_t getElementOffset(const mlir::DataLayout &dataLayout, unsigned idx) const
bool isMatchingAddressSpace(mlir::ptr::MemorySpaceAttrInterface cirAS, clang::LangAS as)
cir::LangAddressSpace toCIRLangAddressSpace(clang::LangAS langAS)
bool isValidFundamentalIntWidth(unsigned width)
cir::FPTypeInterface getFloatingPointType(const llvm::fltSemantics &sem, mlir::MLIRContext *ctx)
Returns the CIR floating-point type for the given semantics, or a null type if CIR has no type for it...
mlir::ptr::MemorySpaceAttrInterface toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS)
Convert an AST LangAS to the appropriate CIR address space attribute interface.
mlir::ptr::MemorySpaceAttrInterface normalizeDefaultAddressSpace(mlir::ptr::MemorySpaceAttrInterface addrSpace)
Normalize LangAddressSpace::Default to null (empty attribute).
bool isSized(mlir::Type ty)
Returns true if the type is a CIR sized type.
bool isSupportedCIRMemorySpaceAttr(mlir::ptr::MemorySpaceAttrInterface memorySpace)
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
StringRef getName(const HeaderType T)
bool isTargetAddressSpace(LangAS AS)
unsigned toTargetAddressSpace(LangAS AS)
LangAS
Defines the address space values used by the address space qualifier of QualType.
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()