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);
67 return !ty.walk([](mlir::Type t) {
69 return mlir::WalkResult::advance();
70 return mlir::isa<cir::CIRDialect>(t.getDialect())
71 ? mlir::WalkResult::advance()
72 : mlir::WalkResult::interrupt();
80static mlir::ParseResult
84 mlir::ArrayRef<mlir::Type> params,
90static mlir::ParseResult
95 mlir::ArrayRef<mlir::Type> params,
104 mlir::ptr::MemorySpaceAttrInterface &attr);
107 mlir::ptr::MemorySpaceAttrInterface attr);
111 cir::TargetAddressSpaceAttr &attr);
114 cir::TargetAddressSpaceAttr attr);
122#include "clang/CIR/Dialect/IR/CIRTypeConstraints.cpp.inc"
126#define GET_TYPEDEF_CLASSES
127#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
136Type CIRDialect::parseType(DialectAsmParser &parser)
const {
137 llvm::SMLoc typeLoc = parser.getCurrentLocation();
138 llvm::StringRef mnemonic;
142 OptionalParseResult parseResult =
143 generatedTypeParser(parser, &mnemonic, genType);
144 if (parseResult.has_value())
148 parser.emitError(typeLoc) <<
"unknown CIR type: " << mnemonic;
152void CIRDialect::printType(Type type, DialectAsmPrinter &os)
const {
154 if (generatedTypePrinter(type, os).succeeded())
158 llvm::report_fatal_error(
"printer is missing a handler for this type");
170 RecordMemberKind::Data);
175static mlir::LogicalResult
179 if (memberKinds.size() != numMembers)
180 return emitError() <<
"expected " << numMembers <<
" member kinds, got "
181 << memberKinds.size();
182 return mlir::success();
190static std::optional<RecordMemberKind>
192 llvm::StringRef keyword;
193 const llvm::SMLoc loc = parser.getCurrentLocation();
194 if (parser.parseKeyword(&keyword).failed())
196 std::optional<RecordMemberKind>
kind = symbolizeRecordMemberKind(keyword);
198 parser.emitError(loc,
"expected a record member kind");
205static mlir::ParseResult
209 assert(incomplete &&
"caller must pre-initialize incomplete to true");
210 if (parser.parseOptionalKeyword(
"incomplete").succeeded())
211 return mlir::success();
213 return parser.parseCommaSeparatedList(
214 AsmParser::Delimiter::Braces,
215 [&parser, &members, &memberKinds]() -> mlir::ParseResult {
218 return mlir::failure();
219 memberKinds.push_back(*
kind);
220 return parser.parseType(members.emplace_back());
228template <
typename RecordTy>
231 bool hasClassPrefix,
bool isPacked,
bool isIncomplete,
240 FailureOr<AsmPrinter::CyclicPrintReset> cyclicPrintGuard =
241 printer.tryStartCyclicPrint(self);
242 if (failed(cyclicPrintGuard)) {
247 if (hasClassPrefix || name)
250 printer <<
"packed ";
252 printer <<
"incomplete";
255 for (
auto [idx, member] : llvm::enumerate(members)) {
258 printer << stringifyRecordMemberKind(memberKinds[idx]) <<
' ';
259 printer.printType(member);
263 printer <<
", padding = {";
264 printer.printType(padding);
272Type StructType::parse(mlir::AsmParser &parser) {
273 FailureOr<AsmParser::CyclicParseReset> cyclicParseGuard;
274 const llvm::SMLoc loc = parser.getCurrentLocation();
275 const mlir::Location eLoc = parser.getEncodedSourceLoc(loc);
277 mlir::MLIRContext *context = parser.getContext();
279 if (parser.parseLess())
283 bool is_class = parser.parseOptionalKeyword(
"class").succeeded();
285 mlir::StringAttr
name;
286 parser.parseOptionalAttribute(name);
289 if (name && parser.parseOptionalGreater().succeeded()) {
290 StructType
type = StructType::getChecked(eLoc, context, name, is_class);
291 if (succeeded(parser.tryStartCyclicParse(type))) {
292 parser.emitError(loc,
"invalid self-reference within record");
300 StructType
type = StructType::getChecked(eLoc, context, name, is_class);
301 cyclicParseGuard = parser.tryStartCyclicParse(type);
302 if (failed(cyclicParseGuard)) {
303 parser.emitError(loc,
"record already defined");
308 if (parser.parseOptionalKeyword(
"packed").succeeded())
311 bool incomplete =
true;
312 llvm::SmallVector<mlir::Type> members;
313 llvm::SmallVector<RecordMemberKind> memberKinds;
314 if (
parseRecordBody(parser, incomplete, members, memberKinds).failed())
317 if (parser.parseGreater())
320 ArrayRef<mlir::Type> membersRef(members);
321 ArrayRef<RecordMemberKind> kindsRef(memberKinds);
322 mlir::Type
type = {};
323 if (name && incomplete) {
324 type = StructType::getChecked(eLoc, context, name, is_class);
325 }
else if (!name && !incomplete) {
326 type = StructType::getChecked(eLoc, context, membersRef, packed, is_class,
330 }
else if (!incomplete) {
331 type = StructType::getChecked(eLoc, context, membersRef, name, packed,
335 if (
auto structTy = mlir::dyn_cast<StructType>(type))
336 if (structTy.isIncomplete())
337 structTy.complete(membersRef, packed, kindsRef);
340 parser.emitError(loc,
"anonymous records must be complete");
347void StructType::print(mlir::AsmPrinter &printer)
const {
349 isIncomplete(), getMembers(), {},
353mlir::LogicalResult StructType::verify(
354 function_ref<mlir::InFlightDiagnostic()> emitError,
355 llvm::ArrayRef<mlir::Type> members, mlir::StringAttr name,
bool incomplete,
356 bool packed, llvm::ArrayRef<RecordMemberKind> member_kinds,
bool is_class) {
357 if (name &&
name.getValue().empty())
358 return emitError() <<
"identified records cannot have an empty name";
364llvm::ArrayRef<mlir::Type> StructType::getMembers()
const {
367mlir::StringAttr StructType::getName()
const {
return getImpl()->name; }
368bool StructType::isIncomplete()
const {
return getImpl()->incomplete; }
369bool StructType::getIncomplete()
const {
return getImpl()->incomplete; }
370bool StructType::getPacked()
const {
return getImpl()->packed; }
371llvm::ArrayRef<RecordMemberKind> StructType::getMemberKinds()
const {
372 return getImpl()->member_kinds;
374bool StructType::getIsClass()
const {
return getImpl()->is_class; }
376bool StructType::getPadded()
const {
377 return llvm::is_contained(getMemberKinds(), RecordMemberKind::Pad);
380bool StructType::isABIConvertedRecord()
const {
381 return getName() &&
getName().getValue().starts_with(abi_conversion_prefix);
384mlir::StringAttr StructType::getABIConvertedName()
const {
385 assert(!isABIConvertedRecord());
386 return StringAttr::get(getContext(),
387 abi_conversion_prefix +
getName().getValue());
390void StructType::removeABIConversionNamePrefix() {
391 mlir::StringAttr recordName =
getName();
392 if (recordName && recordName.getValue().starts_with(abi_conversion_prefix))
393 getImpl()->name = mlir::StringAttr::get(
394 recordName.getValue().drop_front(
sizeof(abi_conversion_prefix) - 1),
395 recordName.getType());
398void StructType::complete(ArrayRef<Type> members,
bool packed,
399 ArrayRef<RecordMemberKind> memberKinds) {
401 if (mutate(members, packed, memberKinds).failed())
402 llvm_unreachable(
"failed to complete struct");
405bool StructType::isLayoutIdentical(
const StructType &other) {
406 if (
getImpl() == other.getImpl())
408 if (getPacked() != other.getPacked())
410 return getMembers() == other.getMembers();
417Type UnionType::parse(mlir::AsmParser &parser) {
418 FailureOr<AsmParser::CyclicParseReset> cyclicParseGuard;
419 const llvm::SMLoc loc = parser.getCurrentLocation();
420 const mlir::Location eLoc = parser.getEncodedSourceLoc(loc);
423 mlir::MLIRContext *context = parser.getContext();
425 if (parser.parseLess())
428 mlir::StringAttr
name;
429 parser.parseOptionalAttribute(name);
432 if (name && parser.parseOptionalGreater().succeeded()) {
433 UnionType
type = UnionType::getChecked(eLoc, context, name);
434 if (succeeded(parser.tryStartCyclicParse(type))) {
435 parser.emitError(loc,
"invalid self-reference within record");
443 UnionType
type = UnionType::getChecked(eLoc, context, name);
444 cyclicParseGuard = parser.tryStartCyclicParse(type);
445 if (failed(cyclicParseGuard)) {
446 parser.emitError(loc,
"record already defined");
451 if (parser.parseOptionalKeyword(
"packed").succeeded())
454 bool incomplete =
true;
455 llvm::SmallVector<mlir::Type> members;
456 llvm::SmallVector<RecordMemberKind> memberKinds;
457 if (
parseRecordBody(parser, incomplete, members, memberKinds).failed())
462 if (!incomplete && parser.parseOptionalComma().succeeded()) {
463 if (parser.parseKeyword(
"padding").failed())
465 if (parser.parseEqual().failed())
467 if (parser.parseLBrace().failed())
469 const llvm::SMLoc paddingLoc = parser.getCurrentLocation();
470 llvm::StringRef paddingKeyword;
473 parser.emitError(paddingLoc,
"a union's tail padding takes no kind mark");
476 if (parser.parseType(padding).failed())
478 if (parser.parseRBrace().failed())
482 if (parser.parseGreater())
485 ArrayRef<mlir::Type> membersRef(members);
486 ArrayRef<RecordMemberKind> kindsRef(memberKinds);
487 mlir::Type
type = {};
488 if (name && incomplete) {
489 type = UnionType::getChecked(eLoc, context, name);
490 }
else if (!name && !incomplete) {
491 type = UnionType::getChecked(eLoc, context, membersRef, packed, padding,
495 }
else if (!incomplete) {
496 type = UnionType::getChecked(eLoc, context, membersRef, name, packed,
500 if (
auto unionTy = mlir::dyn_cast<UnionType>(type))
501 if (unionTy.isIncomplete())
502 unionTy.complete(membersRef, packed, padding, kindsRef);
505 parser.emitError(loc,
"anonymous records must be complete");
512void UnionType::print(mlir::AsmPrinter &printer)
const {
514 getPacked(), isIncomplete(), getMembers(), getPadding(),
519UnionType::verify(function_ref<mlir::InFlightDiagnostic()> emitError,
520 llvm::ArrayRef<mlir::Type> members, mlir::StringAttr name,
521 bool incomplete,
bool packed, mlir::Type padding,
522 llvm::ArrayRef<RecordMemberKind> member_kinds) {
523 if (name &&
name.getValue().empty())
524 return emitError() <<
"identified records cannot have an empty name";
528 if (llvm::is_contained(member_kinds, RecordMemberKind::Pad))
529 return emitError() <<
"a union member cannot be marked pad";
534llvm::ArrayRef<mlir::Type> UnionType::getMembers()
const {
537mlir::StringAttr UnionType::getName()
const {
return getImpl()->name; }
538bool UnionType::isIncomplete()
const {
return getImpl()->incomplete; }
539bool UnionType::getIncomplete()
const {
return getImpl()->incomplete; }
540bool UnionType::getPacked()
const {
return getImpl()->packed; }
541bool UnionType::getPadded()
const {
return getPadding() ?
true :
false; }
542mlir::Type UnionType::getPadding()
const {
return getImpl()->padding; }
543llvm::ArrayRef<RecordMemberKind> UnionType::getMemberKinds()
const {
544 return getImpl()->member_kinds;
547bool UnionType::isABIConvertedRecord()
const {
548 return getName() &&
getName().getValue().starts_with(abi_conversion_prefix);
551mlir::StringAttr UnionType::getABIConvertedName()
const {
552 assert(!isABIConvertedRecord());
553 return StringAttr::get(getContext(),
554 abi_conversion_prefix +
getName().getValue());
557void UnionType::removeABIConversionNamePrefix() {
558 mlir::StringAttr recordName =
getName();
559 if (recordName && recordName.getValue().starts_with(abi_conversion_prefix))
560 getImpl()->name = mlir::StringAttr::get(
561 recordName.getValue().drop_front(
sizeof(abi_conversion_prefix) - 1),
562 recordName.getType());
565void UnionType::complete(ArrayRef<Type> members,
bool packed,
567 ArrayRef<RecordMemberKind> memberKinds) {
569 if (mutate(members, packed, padding, memberKinds).failed())
570 llvm_unreachable(
"failed to complete union");
574UnionType::getUnionStorageType(
const mlir::DataLayout &dataLayout)
const {
575 return getUnionStorageType(dataLayout, getMembers());
578mlir::Type UnionType::getUnionStorageType(
const mlir::DataLayout &dataLayout,
579 llvm::ArrayRef<mlir::Type> members) {
582 return *std::max_element(
583 members.begin(), members.end(), [&](mlir::Type lhs, mlir::Type rhs) {
584 return dataLayout.getTypeABIAlignment(lhs) <
585 dataLayout.getTypeABIAlignment(rhs) ||
586 (dataLayout.getTypeABIAlignment(lhs) ==
587 dataLayout.getTypeABIAlignment(rhs) &&
588 dataLayout.getTypeSize(lhs) < dataLayout.getTypeSize(rhs));
592bool UnionType::isLayoutIdentical(
const UnionType &other) {
593 if (
getImpl() == other.getImpl())
595 return getMembers() == other.getMembers() &&
596 getPadding() == other.getPadding();
604 if (
auto s = mlir::dyn_cast<StructType>(*
this))
605 return s.getMembers();
606 return mlir::cast<UnionType>(*this).getMembers();
609 if (
auto s = mlir::dyn_cast<StructType>(*
this))
611 return mlir::cast<UnionType>(*this).getName();
614 if (
auto s = mlir::dyn_cast<StructType>(*
this))
615 return s.isIncomplete();
616 return mlir::cast<UnionType>(*this).isIncomplete();
619 if (
auto s = mlir::dyn_cast<StructType>(*
this))
620 return s.getPacked();
621 return mlir::cast<UnionType>(*this).getPacked();
624 if (
auto s = mlir::dyn_cast<StructType>(*
this))
625 return s.getPadded();
626 return mlir::cast<UnionType>(*this).getPadded();
629 if (
auto s = mlir::dyn_cast<StructType>(*
this))
630 return s.getMemberKinds();
631 return mlir::cast<UnionType>(*this).getMemberKinds();
634 if (
auto s = mlir::dyn_cast<StructType>(*
this))
639 if (
auto s = mlir::dyn_cast<StructType>(*
this))
644 if (mlir::isa<UnionType>(*
this))
646 return mlir::cast<StructType>(*this).getKindAsStr();
654 if (
auto s = mlir::dyn_cast<StructType>(*
this)) {
655 assert(!padding &&
"only a union takes a separate padding slot");
656 return s.complete(members, packed, memberKinds);
658 return mlir::cast<UnionType>(*this).complete(members, packed, padding,
662 unsigned idx)
const {
663 if (mlir::isa<UnionType>(*
this))
665 return mlir::cast<StructType>(*this).getElementOffset(dataLayout, idx);
668 if (
auto s = mlir::dyn_cast<StructType>(*
this)) {
669 if (
auto so = mlir::dyn_cast<StructType>(other))
670 return s.isLayoutIdentical(so);
673 if (
auto u = mlir::dyn_cast<UnionType>(*
this)) {
674 if (
auto uo = mlir::dyn_cast<UnionType>(other))
675 return u.isLayoutIdentical(uo);
681 if (
auto s = mlir::dyn_cast<StructType>(*
this))
682 return s.isABIConvertedRecord();
683 return mlir::cast<UnionType>(*this).isABIConvertedRecord();
686 if (
auto s = mlir::dyn_cast<StructType>(*
this))
687 return s.getABIConvertedName();
688 return mlir::cast<UnionType>(*this).getABIConvertedName();
691 if (
auto s = mlir::dyn_cast<StructType>(*
this))
692 return s.removeABIConversionNamePrefix();
693 return mlir::cast<UnionType>(*this).removeABIConversionNamePrefix();
711constexpr static uint64_t kBitsInByte = 8;
714constexpr static uint64_t kDefaultPointerSizeBits = 64;
715constexpr static uint64_t kDefaultPointerAlignment = 8;
719cir::PtrSpecAttr getPointerSpec(mlir::DataLayoutEntryListRef params,
720 cir::PointerType type) {
723 for (mlir::DataLayoutEntryInterface entry : params) {
724 if (!entry.isTypeEntry())
727 mlir::cast<cir::PointerType>(mlir::cast<mlir::Type>(entry.getKey()));
728 if (key.getAddrSpace())
730 if (
auto spec = mlir::dyn_cast<cir::PtrSpecAttr>(entry.getValue()))
733 return cir::PtrSpecAttr::get(type.getContext(), kDefaultPointerSizeBits,
734 kDefaultPointerAlignment * kBitsInByte,
735 kDefaultPointerAlignment * kBitsInByte,
736 kDefaultPointerSizeBits);
741PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
742 ::mlir::DataLayoutEntryListRef params)
const {
743 return llvm::TypeSize::getFixed(getPointerSpec(params, *
this).getSize());
747PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
748 ::mlir::DataLayoutEntryListRef params)
const {
749 return getPointerSpec(params, *
this).getAbi() / kBitsInByte;
752uint64_t PointerType::getPreferredAlignment(
753 const ::mlir::DataLayout &dataLayout,
754 ::mlir::DataLayoutEntryListRef params)
const {
755 return getPointerSpec(params, *
this).getPreferred() / kBitsInByte;
758std::optional<uint64_t>
759PointerType::getIndexBitwidth(const ::mlir::DataLayout &dataLayout,
760 ::mlir::DataLayoutEntryListRef params)
const {
761 cir::PtrSpecAttr spec = getPointerSpec(params, *
this);
762 if (spec.getIndex() == cir::PtrSpecAttr::kOptionalSpecValue)
763 return spec.getSize();
764 return spec.getIndex();
768PointerType::verifyEntries(mlir::DataLayoutEntryListRef entries,
769 mlir::Location loc)
const {
770 for (mlir::DataLayoutEntryInterface entry : entries) {
771 if (!entry.isTypeEntry())
773 auto key = mlir::cast<PointerType>(mlir::cast<mlir::Type>(entry.getKey()));
774 if (!mlir::isa<cir::PtrSpecAttr>(entry.getValue()))
775 return mlir::emitError(loc) <<
"expected layout attribute for " << key
776 <<
" to be a #cir.ptr_spec attribute";
777 if (!mlir::isa<cir::VoidType>(key.getPointee()))
778 return mlir::emitError(loc) <<
"expected !cir.ptr data layout entry for "
779 << key <<
" to use !cir.void as pointee";
781 if (key.getAddrSpace())
782 return mlir::emitError(loc)
783 <<
"!cir.ptr data layout entries are currently limited to the "
784 "default address space";
786 return mlir::success();
789bool PointerType::areCompatible(
790 mlir::DataLayoutEntryListRef oldLayout,
791 mlir::DataLayoutEntryListRef newLayout, mlir::DataLayoutSpecInterface,
792 const mlir::DataLayoutIdentifiedEntryMap &)
const {
795 cir::PtrSpecAttr oldSpec = getPointerSpec(oldLayout, *
this);
798 for (mlir::DataLayoutEntryInterface newEntry : newLayout) {
799 if (!newEntry.isTypeEntry())
801 auto newSpec = mlir::cast<cir::PtrSpecAttr>(newEntry.getValue());
802 if (size != newSpec.getSize() || abi < newSpec.getAbi() ||
803 abi % newSpec.getAbi() != 0)
810StructType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
811 mlir::DataLayoutEntryListRef params)
const {
812 auto recordSize =
static_cast<uint64_t>(computeStructSize(dataLayout));
813 return llvm::TypeSize::getFixed(recordSize * 8);
817StructType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
818 ::mlir::DataLayoutEntryListRef params)
const {
822 return computeStructAlignment(dataLayout);
829UnionType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
830 mlir::DataLayoutEntryListRef params)
const {
831 llvm::TypeSize size = llvm::TypeSize::getFixed(0);
832 if (mlir::Type storage = getUnionStorageType(dataLayout))
833 size += dataLayout.getTypeSizeInBits(storage);
834 if (mlir::Type pad = getPadding())
835 size += dataLayout.getTypeSizeInBits(pad);
840UnionType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
841 ::mlir::DataLayoutEntryListRef params)
const {
842 mlir::Type storage = getUnionStorageType(dataLayout);
845 return dataLayout.getTypeABIAlignment(storage);
849StructType::computeStructSize(
const mlir::DataLayout &dataLayout)
const {
850 assert(isComplete() &&
"Cannot get layout of incomplete records");
853 unsigned recordSize = 0;
856 for (mlir::Type ty : getMembers()) {
860 (getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
864 recordSize = llvm::alignTo(recordSize, tyAlign);
865 recordSize += dataLayout.getTypeSize(ty);
869 recordAlignment = std::max(tyAlign, recordAlignment);
874 recordSize = llvm::alignTo(recordSize, recordAlignment);
879StructType::computeStructDataSize(
const mlir::DataLayout &dataLayout)
const {
880 assert(isComplete() &&
"Cannot get layout of incomplete records");
885 llvm::ArrayRef<mlir::Type> members = getMembers();
886 llvm::ArrayRef<RecordMemberKind> kinds = getMemberKinds();
887 assert(kinds.size() == members.size() &&
888 "the two drop_back calls below must stay in step");
889 while (!kinds.empty() && kinds.back() == RecordMemberKind::Pad) {
890 kinds = kinds.drop_back();
891 members = members.drop_back();
894 unsigned recordSize = 0;
895 for (mlir::Type ty : members) {
897 (getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
898 recordSize = llvm::alignTo(recordSize, tyAlign);
899 recordSize += dataLayout.getTypeSize(ty);
909StructType::computeStructAlignment(
const mlir::DataLayout &dataLayout)
const {
910 assert(isComplete() &&
"Cannot get layout of incomplete records");
913 for (mlir::Type ty : getMembers())
915 std::max(dataLayout.getTypeABIAlignment(ty), recordAlignment);
916 return recordAlignment;
919uint64_t StructType::getElementOffset(const ::mlir::DataLayout &dataLayout,
920 unsigned idx)
const {
921 assert(idx < getMembers().size() &&
"access not valid");
925 assert(isComplete() &&
"Cannot get layout of incomplete records");
926 assert(idx < getNumElements());
927 llvm::ArrayRef<mlir::Type> members = getMembers();
931 llvm::make_range(members.begin(), std::next(members.begin(), idx))) {
932 const llvm::Align tyAlign =
933 llvm::Align(getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
934 offset = llvm::alignTo(offset, tyAlign);
935 offset += dataLayout.getTypeSize(ty);
938 const llvm::Align tyAlign = llvm::Align(
939 getPacked() ? 1 : dataLayout.getTypeABIAlignment(members[idx]));
940 offset = llvm::alignTo(offset, tyAlign);
948Type IntType::parse(mlir::AsmParser &parser) {
949 mlir::MLIRContext *context = parser.getBuilder().getContext();
950 llvm::SMLoc loc = parser.getCurrentLocation();
954 if (parser.parseLess())
958 llvm::StringRef
sign;
959 if (parser.parseKeyword(&
sign))
963 else if (
sign ==
"u")
966 parser.emitError(loc,
"expected 's' or 'u'");
970 if (parser.parseComma())
974 if (parser.parseInteger(width))
976 if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
977 parser.emitError(loc,
"expected integer width to be from ")
978 << IntType::minBitwidth() <<
" up to " << IntType::maxBitwidth();
982 bool isBitInt =
false;
983 if (succeeded(parser.parseOptionalComma())) {
985 if (parser.parseKeyword(&kw) || kw !=
"bitint") {
986 parser.emitError(loc,
"expected 'bitint'");
992 if (parser.parseGreater())
995 return IntType::get(context, width, isSigned, isBitInt);
998void IntType::print(mlir::AsmPrinter &printer)
const {
999 char sign = isSigned() ?
's' :
'u';
1000 printer <<
'<' <<
sign <<
", " << getWidth();
1002 printer <<
", bitint";
1007IntType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1008 mlir::DataLayoutEntryListRef params)
const {
1009 return llvm::TypeSize::getFixed(getWidth());
1012uint64_t IntType::getABIAlignment(
const mlir::DataLayout &dataLayout,
1013 mlir::DataLayoutEntryListRef params)
const {
1014 unsigned width = getWidth();
1019 std::min(llvm::PowerOf2Ceil(width),
static_cast<uint64_t>(64));
1020 return std::max(alignBits / 8,
static_cast<uint64_t>(1));
1027 uint64_t alignBits = llvm::PowerOf2Ceil(width);
1028 return std::max(alignBits / 8,
static_cast<uint64_t>(1));
1032IntType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1033 unsigned width,
bool isSigned,
bool isBitInt) {
1034 if (width < IntType::minBitwidth() || width > IntType::maxBitwidth())
1035 return emitError() <<
"IntType only supports widths from "
1036 << IntType::minBitwidth() <<
" up to "
1037 << IntType::maxBitwidth();
1038 return mlir::success();
1042 return width == 8 || width == 16 || width == 32 || width == 64;
1049const llvm::fltSemantics &SingleType::getFloatSemantics()
const {
1050 return llvm::APFloat::IEEEsingle();
1054SingleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1055 mlir::DataLayoutEntryListRef params)
const {
1056 return llvm::TypeSize::getFixed(getWidth());
1060SingleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
1061 mlir::DataLayoutEntryListRef params)
const {
1062 return (uint64_t)(getWidth() / 8);
1065const llvm::fltSemantics &DoubleType::getFloatSemantics()
const {
1066 return llvm::APFloat::IEEEdouble();
1070DoubleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1071 mlir::DataLayoutEntryListRef params)
const {
1072 return llvm::TypeSize::getFixed(getWidth());
1076DoubleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
1077 mlir::DataLayoutEntryListRef params)
const {
1078 return (uint64_t)(getWidth() / 8);
1081const llvm::fltSemantics &FP16Type::getFloatSemantics()
const {
1082 return llvm::APFloat::IEEEhalf();
1086FP16Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1087 mlir::DataLayoutEntryListRef params)
const {
1088 return llvm::TypeSize::getFixed(getWidth());
1091uint64_t FP16Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
1092 mlir::DataLayoutEntryListRef params)
const {
1093 return (uint64_t)(getWidth() / 8);
1096const llvm::fltSemantics &BF16Type::getFloatSemantics()
const {
1097 return llvm::APFloat::BFloat();
1101BF16Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1102 mlir::DataLayoutEntryListRef params)
const {
1103 return llvm::TypeSize::getFixed(getWidth());
1106uint64_t BF16Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
1107 mlir::DataLayoutEntryListRef params)
const {
1108 return (uint64_t)(getWidth() / 8);
1111const llvm::fltSemantics &FP80Type::getFloatSemantics()
const {
1112 return llvm::APFloat::x87DoubleExtended();
1116FP80Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1117 mlir::DataLayoutEntryListRef params)
const {
1119 return llvm::TypeSize::getFixed(128);
1122uint64_t FP80Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
1123 mlir::DataLayoutEntryListRef params)
const {
1127const llvm::fltSemantics &FP128Type::getFloatSemantics()
const {
1128 return llvm::APFloat::IEEEquad();
1132FP128Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1133 mlir::DataLayoutEntryListRef params)
const {
1134 return llvm::TypeSize::getFixed(getWidth());
1137uint64_t FP128Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
1138 mlir::DataLayoutEntryListRef params)
const {
1142const llvm::fltSemantics &LongDoubleType::getFloatSemantics()
const {
1143 return mlir::cast<cir::FPTypeInterface>(getUnderlying()).getFloatSemantics();
1147LongDoubleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1148 mlir::DataLayoutEntryListRef params)
const {
1149 return mlir::cast<mlir::DataLayoutTypeInterface>(getUnderlying())
1150 .getTypeSizeInBits(dataLayout, params);
1154LongDoubleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
1155 mlir::DataLayoutEntryListRef params)
const {
1156 return mlir::cast<mlir::DataLayoutTypeInterface>(getUnderlying())
1157 .getABIAlignment(dataLayout, params);
1165cir::ComplexType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1166 mlir::DataLayoutEntryListRef params)
const {
1172 return dataLayout.getTypeSizeInBits(getElementType()) * 2;
1176cir::ComplexType::getABIAlignment(
const mlir::DataLayout &dataLayout,
1177 mlir::DataLayoutEntryListRef params)
const {
1183 return dataLayout.getTypeABIAlignment(getElementType());
1186FuncType FuncType::clone(TypeRange inputs, TypeRange results)
const {
1187 assert(results.size() == 1 &&
"expected exactly one result type");
1188 return get(llvm::to_vector(inputs), results[0], isVarArg());
1192static mlir::ParseResult
1196 return p.parseCommaSeparatedList(
1197 AsmParser::Delimiter::Paren, [&]() -> mlir::ParseResult {
1199 return p.emitError(p.getCurrentLocation(),
1200 "variadic `...` must be the last parameter");
1201 if (succeeded(p.parseOptionalEllipsis())) {
1206 if (failed(p.parseType(type)))
1208 params.push_back(type);
1214 mlir::ArrayRef<mlir::Type> params,
1217 llvm::interleaveComma(params, p,
1218 [&p](mlir::Type type) { p.printType(type); });
1220 if (!params.empty())
1229mlir::Type FuncType::getReturnType()
const {
1230 if (hasVoidReturn())
1231 return cir::VoidType::get(getContext());
1232 return getOptionalReturnType();
1238llvm::ArrayRef<mlir::Type> FuncType::getReturnTypes()
const {
1239 if (hasVoidReturn())
1244 return getImpl()->optionalReturnType;
1248bool FuncType::hasVoidReturn()
const {
return !getOptionalReturnType(); }
1251FuncType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1252 llvm::ArrayRef<mlir::Type> argTypes, mlir::Type returnType,
1254 if (mlir::isa_and_nonnull<cir::VoidType>(returnType))
1256 <<
"!cir.func cannot have an explicit 'void' return type";
1260 for (mlir::Type type : argTypes) {
1263 <<
"expected all types in the function signature to be CIR types";
1267 <<
"expected all types in the function signature to be CIR types";
1269 return mlir::success();
1281 auto voidPtrTy = cir::PointerType::get(cir::VoidType::get(ctx));
1282 mlir::Type fields[2]{voidPtrTy, voidPtrTy};
1283 return cir::StructType::get(ctx, fields,
false,
1289MethodType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1290 mlir::DataLayoutEntryListRef params)
const {
1295MethodType::getABIAlignment(
const mlir::DataLayout &dataLayout,
1296 mlir::DataLayoutEntryListRef params)
const {
1298 .getABIAlignment(dataLayout, params);
1306BoolType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
1307 ::mlir::DataLayoutEntryListRef params)
const {
1308 return llvm::TypeSize::getFixed(8);
1312BoolType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
1313 ::mlir::DataLayoutEntryListRef params)
const {
1322 mlir::MLIRContext *ctx) {
1326 auto voidPtrTy = cir::PointerType::get(cir::VoidType::get(ctx));
1327 uint64_t width = dataLayout.getTypeIndexBitwidth(voidPtrTy).value_or(
1328 dataLayout.getTypeSizeInBits(voidPtrTy).getFixedValue());
1329 return cir::IntType::get(ctx, width,
true);
1333DataMemberType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
1334 ::mlir::DataLayoutEntryListRef params)
const {
1336 return dataLayout.getTypeSizeInBits(
1341DataMemberType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
1342 ::mlir::DataLayoutEntryListRef params)
const {
1344 return dataLayout.getTypeABIAlignment(
1353VPtrType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
1354 mlir::DataLayoutEntryListRef params)
const {
1356 return dataLayout.getTypeSizeInBits(
1357 cir::PointerType::get(cir::VoidType::get(getContext())));
1360uint64_t VPtrType::getABIAlignment(
const mlir::DataLayout &dataLayout,
1361 mlir::DataLayoutEntryListRef params)
const {
1362 return dataLayout.getTypeABIAlignment(
1363 cir::PointerType::get(cir::VoidType::get(getContext())));
1371ArrayType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
1372 ::mlir::DataLayoutEntryListRef params)
const {
1373 return getSize() * dataLayout.getTypeSizeInBits(getElementType());
1377ArrayType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
1378 ::mlir::DataLayoutEntryListRef params)
const {
1379 return dataLayout.getTypeABIAlignment(getElementType());
1386llvm::TypeSize cir::VectorType::getTypeSizeInBits(
1387 const ::mlir::DataLayout &dataLayout,
1388 ::mlir::DataLayoutEntryListRef params)
const {
1389 return llvm::TypeSize::getFixed(
1390 getSize() * dataLayout.getTypeSizeInBits(getElementType()));
1394cir::VectorType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
1395 ::mlir::DataLayoutEntryListRef params)
const {
1397 return llvm::PowerOf2Ceil(
1398 llvm::divideCeil(dataLayout.getTypeSizeInBits(*
this), 8u));
1401mlir::LogicalResult cir::VectorType::verify(
1402 llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1403 mlir::Type elementType, uint64_t size,
bool scalable) {
1405 return emitError() <<
"the number of vector elements must be non-zero";
1409mlir::Type cir::VectorType::parse(::mlir::AsmParser &odsParser) {
1411 llvm::SMLoc odsLoc = odsParser.getCurrentLocation();
1412 mlir::Builder odsBuilder(odsParser.getContext());
1413 mlir::FailureOr<::mlir::Type> elementType;
1414 mlir::FailureOr<uint64_t> size;
1415 bool isScalabe =
false;
1418 if (odsParser.parseLess())
1422 if (odsParser.parseOptionalLSquare().succeeded())
1426 size = mlir::FieldParser<uint64_t>::parse(odsParser);
1427 if (mlir::failed(size)) {
1428 odsParser.emitError(odsParser.getCurrentLocation(),
1429 "failed to parse CIR_VectorType parameter 'size' which "
1430 "is to be a `uint64_t`");
1436 if (isScalabe && odsParser.parseRSquare().failed()) {
1437 odsParser.emitError(odsParser.getCurrentLocation(),
1438 "missing closing `]` for scalable dim size");
1443 if (odsParser.parseKeyword(
"x"))
1447 elementType = mlir::FieldParser<::mlir::Type>::parse(odsParser);
1448 if (mlir::failed(elementType)) {
1449 odsParser.emitError(odsParser.getCurrentLocation(),
1450 "failed to parse CIR_VectorType parameter "
1451 "'elementType' which is to be a `mlir::Type`");
1456 if (odsParser.parseGreater())
1458 return odsParser.getChecked<VectorType>(odsLoc, odsParser.getContext(),
1459 mlir::Type((*elementType)),
1463void cir::VectorType::print(mlir::AsmPrinter &odsPrinter)
const {
1464 mlir::Builder odsBuilder(getContext());
1466 if (this->getIsScalable())
1469 odsPrinter.printStrippedAttrOrType(getSize());
1470 if (this->getIsScalable())
1472 odsPrinter <<
' ' <<
"x";
1474 odsPrinter.printStrippedAttrOrType(getElementType());
1483 mlir::ptr::MemorySpaceAttrInterface memorySpace) {
1484 return mlir::isa<cir::LangAddressSpaceAttr, cir::TargetAddressSpaceAttr>(
1491 case LangAS::Default:
1492 return LangAddressSpace::Default;
1493 case LangAS::opencl_global:
1494 return LangAddressSpace::OffloadGlobal;
1495 case LangAS::opencl_local:
1496 case LangAS::cuda_shared:
1499 return LangAddressSpace::OffloadLocal;
1500 case LangAS::cuda_device:
1501 return LangAddressSpace::OffloadGlobal;
1502 case LangAS::opencl_constant:
1503 case LangAS::cuda_constant:
1504 return LangAddressSpace::OffloadConstant;
1505 case LangAS::opencl_private:
1506 return LangAddressSpace::OffloadPrivate;
1507 case LangAS::opencl_generic:
1508 return LangAddressSpace::OffloadGeneric;
1509 case LangAS::opencl_global_device:
1510 return LangAddressSpace::OffloadGlobalDevice;
1511 case LangAS::opencl_global_host:
1512 return LangAddressSpace::OffloadGlobalHost;
1513 case LangAS::sycl_global:
1514 case LangAS::sycl_global_device:
1515 case LangAS::sycl_global_host:
1516 case LangAS::sycl_local:
1517 case LangAS::sycl_private:
1518 case LangAS::ptr32_sptr:
1519 case LangAS::ptr32_uptr:
1521 case LangAS::hlsl_groupshared:
1522 case LangAS::wasm_funcref:
1523 llvm_unreachable(
"NYI");
1525 llvm_unreachable(
"unknown/unsupported clang language address space");
1531 mlir::ptr::MemorySpaceAttrInterface &attr) {
1533 llvm::SMLoc loc = p.getCurrentLocation();
1537 if (p.parseOptionalKeyword(
"target_address_space").succeeded()) {
1539 if (p.parseLParen())
1540 return p.emitError(loc,
"expected '(' after 'target_address_space'");
1542 if (p.parseInteger(val))
1543 return p.emitError(loc,
"expected target address space value");
1545 if (p.parseRParen())
1546 return p.emitError(loc,
"expected ')'");
1548 attr = cir::TargetAddressSpaceAttr::get(p.getContext(), val);
1549 return mlir::success();
1553 if (p.parseOptionalKeyword(
"lang_address_space").succeeded()) {
1554 if (p.parseLParen())
1555 return p.emitError(loc,
"expected '(' after 'lang_address_space'");
1557 mlir::FailureOr<cir::LangAddressSpace> result =
1558 mlir::FieldParser<cir::LangAddressSpace>::parse(p);
1559 if (mlir::failed(result))
1560 return mlir::failure();
1562 if (p.parseRParen())
1563 return p.emitError(loc,
"expected ')'");
1565 attr = cir::LangAddressSpaceAttr::get(p.getContext(), result.value());
1566 return mlir::success();
1569 llvm::StringRef keyword;
1570 if (p.parseOptionalKeyword(&keyword).succeeded())
1571 return p.emitError(loc,
"unknown address space specifier '")
1572 << keyword <<
"'; expected 'target_address_space' or "
1573 <<
"'lang_address_space'";
1575 return mlir::success();
1579 mlir::ptr::MemorySpaceAttrInterface attr) {
1583 if (
auto language = dyn_cast<cir::LangAddressSpaceAttr>(attr)) {
1584 p <<
"lang_address_space("
1585 << cir::stringifyLangAddressSpace(language.getValue()) <<
')';
1589 if (
auto target = dyn_cast<cir::TargetAddressSpaceAttr>(attr)) {
1590 p <<
"target_address_space(" << target.getValue() <<
')';
1594 llvm_unreachable(
"unexpected address-space attribute kind");
1597mlir::OptionalParseResult
1599 mlir::ptr::MemorySpaceAttrInterface &attr) {
1601 mlir::SMLoc loc = p.getCurrentLocation();
1603 return p.emitError(loc,
"failed to parse Address Space Value for GlobalOp");
1604 return mlir::success();
1608 mlir::ptr::MemorySpaceAttrInterface attr) {
1613 mlir::ptr::MemorySpaceAttrInterface addrSpace) {
1615 mlir::dyn_cast_if_present<cir::LangAddressSpaceAttr>(addrSpace))
1616 if (langAS.getValue() == cir::LangAddressSpace::Default)
1621mlir::ptr::MemorySpaceAttrInterface
1625 if (langAS == LangAS::Default)
1626 return cir::LangAddressSpaceAttr::get(&ctx, cir::LangAddressSpace::Default);
1630 return cir::TargetAddressSpaceAttr::get(&ctx, targetAS);
1643 return expected == cirAS;
1650mlir::LogicalResult cir::PointerType::verify(
1651 llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1652 mlir::Type pointee, mlir::ptr::MemorySpaceAttrInterface addrSpace) {
1655 return emitError() <<
"unsupported address space attribute; expected "
1656 "'target_address_space' or 'lang_address_space'";
1667void CIRDialect::registerTypes() {
1670#define GET_TYPEDEF_LIST
1671#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)
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 void printRecordBody(mlir::AsmPrinter &printer, RecordTy self, mlir::StringAttr name, bool hasClassPrefix, bool isPacked, bool isIncomplete, llvm::ArrayRef< mlir::Type > members, mlir::Type padding, llvm::ArrayRef< RecordMemberKind > memberKinds)
Print a complete CIR record body: '<' ['class '] [name] ['packed '] body '>' where body is "incomplet...
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 bool isPureCIRType(mlir::Type ty)
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
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
void complete(llvm::ArrayRef< mlir::Type > members, bool packed, mlir::Type padding, llvm::ArrayRef< RecordMemberKind > memberKinds)
padding is union-only.
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 holdsDataForABI(RecordMemberKind kind)
Whether a member of this kind holds data for argument passing.
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()